Sfoglia il codice sorgente

优化, 完善细节

lixiang1994 6 anni fa
parent
commit
698c28d407

+ 24 - 20
Sources/Extensions/ImageView+Kingfisher.swift

@@ -110,9 +110,6 @@ extension KingfisherWrapper where Base: ImageView {
             isContinue: { () -> Bool in
                 issuedIdentifier == self.taskIdentifier
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.imageTask == nil
-            },
             refreshImage: { (image) in
                 self.base.image = image
             }
@@ -124,7 +121,7 @@ extension KingfisherWrapper where Base: ImageView {
             receivedBlock: { latest, received in
                 guard issuedIdentifier == self.taskIdentifier else { return }
                 let callbacks = mutatingSelf.imageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedIdentifier == self.taskIdentifier else { return }
@@ -132,23 +129,23 @@ extension KingfisherWrapper where Base: ImageView {
             },
             completionHandler: { result in
                 CallbackQueue.mainCurrentOrAsync.execute {
-                    maybeIndicator?.stopAnimatingView()
-                    guard issuedIdentifier == self.taskIdentifier else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        maybeIndicator?.stopAnimatingView()
+                        guard issuedIdentifier == self.taskIdentifier else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-                    
-                    mutatingSelf.imageTask = nil
-                    
-                    progressive.finished {
+                        
+                        mutatingSelf.imageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             guard self.needsTransition(options: options, cacheType: value.cacheType) else {
@@ -169,6 +166,13 @@ extension KingfisherWrapper where Base: ImageView {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )

+ 46 - 38
Sources/Extensions/NSButton+Kingfisher.swift

@@ -76,9 +76,6 @@ extension KingfisherWrapper where Base: NSButton {
             isContinue: { () -> Bool in
                 issuedIdentifier == self.taskIdentifier
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.imageTask != nil
-            },
             refreshImage: { (image) in
                 self.base.image = image
             }
@@ -90,7 +87,7 @@ extension KingfisherWrapper where Base: NSButton {
             receivedBlock: { latest, received in
                 guard issuedIdentifier == self.taskIdentifier else { return }
                 let callbacks = mutatingSelf.imageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedIdentifier == self.taskIdentifier else { return }
@@ -98,22 +95,22 @@ extension KingfisherWrapper where Base: NSButton {
             },
             completionHandler: { result in
                 DispatchQueue.main.safeAsync {
-                    guard issuedIdentifier == self.taskIdentifier else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        guard issuedIdentifier == self.taskIdentifier else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-
-                    mutatingSelf.imageTask = nil
-
-                    progressive.finished {
+                        
+                        mutatingSelf.imageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             self.base.image = value.image
@@ -126,6 +123,13 @@ extension KingfisherWrapper where Base: NSButton {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )
@@ -205,9 +209,6 @@ extension KingfisherWrapper where Base: NSButton {
             isContinue: { () -> Bool in
                 issuedIdentifier == self.alternateTaskIdentifier
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.alternateImageTask != nil
-            },
             refreshImage: { (image) in
                 self.base.alternateImage = image
             }
@@ -219,7 +220,7 @@ extension KingfisherWrapper where Base: NSButton {
             receivedBlock: { latest, received in
                 guard issuedIdentifier == self.alternateTaskIdentifier else { return }
                 let callbacks = mutatingSelf.alternateImageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedIdentifier == self.alternateTaskIdentifier else { return }
@@ -227,22 +228,22 @@ extension KingfisherWrapper where Base: NSButton {
             },
             completionHandler: { result in
                 CallbackQueue.mainCurrentOrAsync.execute {
-                    guard issuedIdentifier == self.alternateTaskIdentifier else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        guard issuedIdentifier == self.alternateTaskIdentifier else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-
-                    mutatingSelf.alternateImageTask = nil
-
-                    progressive.finished {
+                        
+                        mutatingSelf.alternateImageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             self.base.alternateImage = value.image
@@ -255,6 +256,13 @@ extension KingfisherWrapper where Base: NSButton {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )

+ 45 - 37
Sources/Extensions/UIButton+Kingfisher.swift

@@ -76,9 +76,6 @@ extension KingfisherWrapper where Base: UIButton {
             isContinue: { () -> Bool in
                 issuedTaskIdentifier == self.taskIdentifier(for: state)
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.imageTask != nil
-            },
             refreshImage: { (image) in
                 self.base.setImage(image, for: state)
             }
@@ -90,7 +87,7 @@ extension KingfisherWrapper where Base: UIButton {
             receivedBlock: { latest, received in
                 guard issuedTaskIdentifier == self.taskIdentifier(for: state) else { return }
                 let callbacks = mutatingSelf.imageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedTaskIdentifier == self.taskIdentifier(for: state) else { return }
@@ -98,22 +95,22 @@ extension KingfisherWrapper where Base: UIButton {
             },
             completionHandler: { result in
                 CallbackQueue.mainCurrentOrAsync.execute {
-                    guard issuedTaskIdentifier == self.taskIdentifier(for: state) else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        guard issuedTaskIdentifier == self.taskIdentifier(for: state) else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-                    
-                    mutatingSelf.imageTask = nil
-                    
-                    progressive.finished {
+                        
+                        mutatingSelf.imageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             self.base.setImage(value.image, for: state)
@@ -126,6 +123,13 @@ extension KingfisherWrapper where Base: UIButton {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )
@@ -226,9 +230,6 @@ extension KingfisherWrapper where Base: UIButton {
             isContinue: { () -> Bool in
                 issuedTaskIdentifier == self.backgroundTaskIdentifier(for: state)
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.backgroundImageTask != nil
-            },
             refreshImage: { (image) in
                 self.base.setBackgroundImage(image, for: state)
             }
@@ -240,7 +241,7 @@ extension KingfisherWrapper where Base: UIButton {
             receivedBlock: { latest, received in
                 guard issuedTaskIdentifier == self.backgroundTaskIdentifier(for: state) else { return }
                 let callbacks = mutatingSelf.backgroundImageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedTaskIdentifier == self.backgroundTaskIdentifier(for: state) else {
@@ -252,21 +253,21 @@ extension KingfisherWrapper where Base: UIButton {
             },
             completionHandler: { result in
                 CallbackQueue.mainCurrentOrAsync.execute {
-                    guard issuedTaskIdentifier == self.backgroundTaskIdentifier(for: state) else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        guard issuedTaskIdentifier == self.backgroundTaskIdentifier(for: state) else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-                    mutatingSelf.backgroundImageTask = nil
-
-                    progressive.finished {
+                        mutatingSelf.backgroundImageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             self.base.setBackgroundImage(value.image, for: state)
@@ -279,6 +280,13 @@ extension KingfisherWrapper where Base: UIButton {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )

+ 23 - 19
Sources/Extensions/WKInterfaceImage+Kingfisher.swift

@@ -76,9 +76,6 @@ extension KingfisherWrapper where Base: WKInterfaceImage {
             isContinue: { () -> Bool in
                 issuedTaskIdentifier == self.taskIdentifier
             },
-            isFinished: { () -> Bool in
-                mutatingSelf.imageTask != nil
-            },
             refreshImage: { (image) in
                 self.base.setImage(image)
             }
@@ -90,7 +87,7 @@ extension KingfisherWrapper where Base: WKInterfaceImage {
             receivedBlock: { latest, received in
                 guard issuedTaskIdentifier == self.taskIdentifier else { return }
                 let callbacks = mutatingSelf.imageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
+                progressive?.update(data: received, with: callbacks)
             },
             progressBlock: { receivedSize, totalSize in
                 guard issuedTaskIdentifier == self.taskIdentifier else { return }
@@ -98,22 +95,22 @@ extension KingfisherWrapper where Base: WKInterfaceImage {
             },
             completionHandler: { result in
                 CallbackQueue.mainCurrentOrAsync.execute {
-                    guard issuedTaskIdentifier == self.taskIdentifier else {
-                        let reason: KingfisherError.ImageSettingErrorReason
-                        do {
-                            let value = try result.get()
-                            reason = .notCurrentSourceTask(result: value, error: nil, source: source)
-                        } catch {
-                            reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                    func handler() {
+                        guard issuedTaskIdentifier == self.taskIdentifier else {
+                            let reason: KingfisherError.ImageSettingErrorReason
+                            do {
+                                let value = try result.get()
+                                reason = .notCurrentSourceTask(result: value, error: nil, source: source)
+                            } catch {
+                                reason = .notCurrentSourceTask(result: nil, error: error, source: source)
+                            }
+                            let error = KingfisherError.imageSettingError(reason: reason)
+                            completionHandler?(.failure(error))
+                            return
                         }
-                        let error = KingfisherError.imageSettingError(reason: reason)
-                        completionHandler?(.failure(error))
-                        return
-                    }
-                    
-                    mutatingSelf.imageTask = nil
-                    
-                    progressive.finished {
+                        
+                        mutatingSelf.imageTask = nil
+                        
                         switch result {
                         case .success(let value):
                             self.base.setImage(value.image)
@@ -126,6 +123,13 @@ extension KingfisherWrapper where Base: WKInterfaceImage {
                             completionHandler?(result)
                         }
                     }
+                    
+                    if let progressive = progressive {
+                        progressive.finished { handler() }
+                        
+                    } else {
+                        handler()
+                    }
                 }
             }
         )

+ 14 - 6
Sources/Image/ImageProgressive.swift

@@ -65,20 +65,21 @@ final class ImageProgressiveProvider {
     private let options: KingfisherParsedOptionsInfo
     private let refreshClosure: (Image) -> Void
     private let isContinueClosure: () -> Bool
-    private let isFinishedClosure: () -> Bool
     private let isWait: Bool
     
     private let decoder: ImageProgressiveDecoder
     private let queue = ImageProgressiveSerialQueue(.main)
     
-    init(_ options: KingfisherParsedOptionsInfo,
+    private var isFinished = false
+    
+    init?(_ options: KingfisherParsedOptionsInfo,
         isContinue: @escaping () -> Bool,
-        isFinished: @escaping () -> Bool,
         refreshImage: @escaping (Image) -> Void) {
+        guard options.progressiveJPEG != nil else { return nil }
+        
         self.options = options
         self.refreshClosure = refreshImage
         self.isContinueClosure = isContinue
-        self.isFinishedClosure = isFinished
         self.decoder = ImageProgressiveDecoder(options)
         self.isWait = options.progressiveJPEG?.isWait ?? false
     }
@@ -99,7 +100,7 @@ final class ImageProgressiveProvider {
                 self.decoder.decode(data, with: callbacks) { (image) in
                     defer { completion() }
                     guard self.isContinueClosure() else { return }
-                    guard self.isWait || !self.isFinishedClosure() else { return }
+                    guard self.isWait || !self.isFinished else { return }
                     guard let image = image else { return }
                     
                     self.refreshClosure(image)
@@ -121,6 +122,9 @@ final class ImageProgressiveProvider {
     }
     
     func finished(_ closure: @escaping () -> Void) {
+        
+        isFinished = true
+        
         if queue.count > 0, isWait {
             queue.notify {
                 guard self.isContinueClosure() else { return }
@@ -269,6 +273,7 @@ fileprivate final class ImageProgressiveSerialQueue {
     private let queue: DispatchQueue
     private var items: [DispatchWorkItem] = []
     private var notify: (() -> Void)?
+    private var lastTime: TimeInterval?
     var count: Int { return items.count }
     
     init(_ queue: DispatchQueue) {
@@ -289,6 +294,7 @@ fileprivate final class ImageProgressiveSerialQueue {
                     )
                     
                 } else {
+                    self.lastTime = Date().timeIntervalSince1970
                     self.notify?()
                     self.notify = nil
                 }
@@ -298,7 +304,9 @@ fileprivate final class ImageProgressiveSerialQueue {
             closure(completion)
         }
         if items.isEmpty {
-            queue.asyncAfter(deadline: .now(), execute: item)
+            let difference = Date().timeIntervalSince1970 - (lastTime ?? 0)
+            let delay = difference > interval ? 0 : interval - difference
+            queue.asyncAfter(deadline: .now() + delay, execute: item)
         }
         items.append(item)
     }