diff --git a/Sources/Gifu/Classes/Animator.swift b/Sources/Gifu/Classes/Animator.swift index 0457968..3010192 100644 --- a/Sources/Gifu/Classes/Animator.swift +++ b/Sources/Gifu/Classes/Animator.swift @@ -8,7 +8,7 @@ public class Animator { var loopDuration: TimeInterval { return frameStore?.loopDuration ?? 0 } - + /// Number of frame to buffer. var frameBufferSize = 50 @@ -60,21 +60,21 @@ public class Animator { /// Checks if there is a new frame to display. fileprivate func updateFrameIfNeeded() { guard let store = frameStore else { return } - + if store.isFinished { - stopAnimating() - if let animationBlock = animationBlock { - animationBlock() - } - return + stopAnimating() + if let animationBlock = animationBlock { + animationBlock() + } + return } - + store.shouldChangeFrame(with: displayLink.duration) { if $0 { - delegate.animatorHasNewFrame() - if store.isLoopFinished, let loopBlock = loopBlock { - loopBlock() - } + delegate.animatorHasNewFrame() + if store.isLoopFinished, let loopBlock = loopBlock { + loopBlock() + } } } } @@ -89,8 +89,8 @@ public class Animator { /// - parameter completionHandler: Completion callback function func prepareForAnimation(withGIFNamed imageName: String, inBundle bundle: Bundle = .main, size: CGSize, contentMode: UIView.ContentMode, loopCount: Int = 0, completionHandler: (() -> Void)? = nil) { guard let extensionRemoved = imageName.components(separatedBy: ".")[safe: 0], - let imagePath = bundle.url(forResource: extensionRemoved, withExtension: "gif"), - let data = try? Data(contentsOf: imagePath) else { return } + let imagePath = bundle.url(forResource: extensionRemoved, withExtension: "gif"), + let data = try? Data(contentsOf: imagePath) else { return } prepareForAnimation(withGIFData: data, size: size, diff --git a/Sources/Gifu/Classes/FrameStore.swift b/Sources/Gifu/Classes/FrameStore.swift index 7a7428f..6bf4ba5 100644 --- a/Sources/Gifu/Classes/FrameStore.swift +++ b/Sources/Gifu/Classes/FrameStore.swift @@ -166,17 +166,6 @@ class FrameStore { } } -extension UIImage { - var memorySize: Int { - guard let cgImage = self.cgImage else { return 0 } - let instanceSize = MemoryLayout.size(ofValue: self) - let pixmapSize = cgImage.height * cgImage.bytesPerRow - let totalSize = instanceSize + pixmapSize - return totalSize - } -} - - private extension FrameStore { /// Optionally loads a single frame from an image source, resizes it if required, then returns an `UIImage`. /// @@ -322,6 +311,10 @@ private extension FrameStore { loadFrameAtIndexIfNeeded(index) } + if #available(iOSApplicationExtension 15.0, *) { + print(#function, "Cache:", totalFrameCacheSize.formatted(.byteCount(style: .memory))) + } + self.loopDuration = duration } @@ -329,5 +322,14 @@ private extension FrameStore { func resetAnimatedFrames() { animatedFrames = [] } + + private var totalFrameCacheSize: Int { + animatedFrames + .filter({ !$0.isPlaceholder }) + .compactMap(\.image) + .reduce(0) { size, image in + size + image.memorySize + } + } } #endif diff --git a/Sources/Gifu/Extensions/UIImage.swift b/Sources/Gifu/Extensions/UIImage.swift index c1368ac..e351a7c 100644 --- a/Sources/Gifu/Extensions/UIImage.swift +++ b/Sources/Gifu/Extensions/UIImage.swift @@ -48,5 +48,14 @@ extension UIImage { class func size(withImageData data: Data) -> CGSize? { return UIImage(data: data)?.size } + + var memorySize: Int { + guard let cgImage = self.cgImage else { return 0 } + let instanceSize = MemoryLayout.size(ofValue: self) + let pixmapSize = cgImage.height * cgImage.bytesPerRow + let totalSize = instanceSize + pixmapSize + return totalSize + } } #endif +