|
|
@@ -131,7 +131,7 @@ open class AnimatedImageView: UIImageView {
|
|
|
/// Set this property to `RunLoop.Mode.default` will make the animation pause during UIScrollView scrolling.
|
|
|
public var runLoopMode = KFRunLoopModeCommon {
|
|
|
willSet {
|
|
|
- guard runLoopMode == newValue else { return }
|
|
|
+ guard runLoopMode != newValue else { return }
|
|
|
stopAnimating()
|
|
|
displayLink.remove(from: .main, forMode: runLoopMode)
|
|
|
displayLink.add(to: .main, forMode: newValue)
|
|
|
@@ -361,7 +361,7 @@ extension AnimatedImageView {
|
|
|
private let maxRepeatCount: RepeatCount
|
|
|
|
|
|
private let maxTimeStep: TimeInterval = 1.0
|
|
|
- private var animatedFrames = [AnimatedFrame]()
|
|
|
+ private let animatedFrames = SafeArray<AnimatedFrame>()
|
|
|
private var frameCount = 0
|
|
|
private var timeSinceLastFrameChange: TimeInterval = 0.0
|
|
|
private var currentRepeatCount: UInt = 0
|
|
|
@@ -450,11 +450,11 @@ extension AnimatedImageView {
|
|
|
}
|
|
|
|
|
|
func frame(at index: Int) -> KFCrossPlatformImage? {
|
|
|
- return animatedFrames[safe: index]?.image
|
|
|
+ return animatedFrames[index]?.image
|
|
|
}
|
|
|
|
|
|
func duration(at index: Int) -> TimeInterval {
|
|
|
- return animatedFrames[safe: index]?.duration ?? .infinity
|
|
|
+ return animatedFrames[index]?.duration ?? .infinity
|
|
|
}
|
|
|
|
|
|
func prepareFramesAsynchronously() {
|
|
|
@@ -485,17 +485,17 @@ extension AnimatedImageView {
|
|
|
(0..<frameCount).forEach { index in
|
|
|
let frameDuration = GIFAnimatedImage.getFrameDuration(from: imageSource, at: index)
|
|
|
duration += min(frameDuration, maxTimeStep)
|
|
|
- animatedFrames += [AnimatedFrame(image: nil, duration: frameDuration)]
|
|
|
+ animatedFrames.append(AnimatedFrame(image: nil, duration: frameDuration))
|
|
|
|
|
|
if index > maxFrameCount { return }
|
|
|
- animatedFrames[index] = animatedFrames[index].makeAnimatedFrame(image: loadFrame(at: index))
|
|
|
+ animatedFrames[index] = animatedFrames[index]?.makeAnimatedFrame(image: loadFrame(at: index))
|
|
|
}
|
|
|
|
|
|
self.loopDuration = duration
|
|
|
}
|
|
|
|
|
|
private func resetAnimatedFrames() {
|
|
|
- animatedFrames = []
|
|
|
+ animatedFrames.removeAll()
|
|
|
}
|
|
|
|
|
|
private func loadFrame(at index: Int) -> UIImage? {
|
|
|
@@ -522,10 +522,10 @@ extension AnimatedImageView {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- animatedFrames[previousFrameIndex] = animatedFrames[previousFrameIndex].placeholderFrame
|
|
|
+ animatedFrames[previousFrameIndex] = animatedFrames[previousFrameIndex]?.placeholderFrame
|
|
|
|
|
|
preloadIndexes(start: currentFrameIndex).forEach { index in
|
|
|
- let currentAnimatedFrame = animatedFrames[index]
|
|
|
+ guard let currentAnimatedFrame = animatedFrames[index] else { return }
|
|
|
if !currentAnimatedFrame.isPlaceholder { return }
|
|
|
animatedFrames[index] = currentAnimatedFrame.makeAnimatedFrame(image: loadFrame(at: index))
|
|
|
}
|
|
|
@@ -566,9 +566,48 @@ extension AnimatedImageView {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-extension Array {
|
|
|
- subscript(safe index: Int) -> Element? {
|
|
|
- return indices ~= index ? self[index] : nil
|
|
|
+class SafeArray<Element> {
|
|
|
+ private var array: Array<Element> = []
|
|
|
+ private let lock = NSLock()
|
|
|
+
|
|
|
+ subscript(index: Int) -> Element? {
|
|
|
+ get {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ return array.indices ~= index ? array[index] : nil
|
|
|
+ }
|
|
|
+
|
|
|
+ set {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ if let newValue = newValue, array.indices ~= index {
|
|
|
+ array[index] = newValue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var count : Int {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ return array.count
|
|
|
+ }
|
|
|
+
|
|
|
+ func reserveCapacity(_ count: Int) {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ array.reserveCapacity(count)
|
|
|
+ }
|
|
|
+
|
|
|
+ func append(_ element: Element) {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ array += [element]
|
|
|
+ }
|
|
|
+
|
|
|
+ func removeAll() {
|
|
|
+ lock.lock()
|
|
|
+ defer { lock.unlock() }
|
|
|
+ array = []
|
|
|
}
|
|
|
}
|
|
|
#endif
|