Parcourir la source

Refactor for ImagePrefetcher

onevcat il y a 9 ans
Parent
commit
f95cbc4b51

+ 8 - 8
Sources/ImageCache.swift

@@ -248,7 +248,7 @@ extension ImageCache {
         let options = options ?? KingfisherEmptyOptionsInfo
         let options = options ?? KingfisherEmptyOptionsInfo
         
         
         if let image = self.retrieveImageInMemoryCacheForKey(key) {
         if let image = self.retrieveImageInMemoryCacheForKey(key) {
-            dispatch_async_safely_to_queue(options.callbackDispatchQueue) { () -> Void in
+            options.callbackDispatchQueue.safeAsync {
                 completionHandler(image, .memory)
                 completionHandler(image, .memory)
             }
             }
         } else {
         } else {
@@ -261,24 +261,24 @@ extension ImageCache {
                             let result = image.kf_decoded(scale: options.scaleFactor)
                             let result = image.kf_decoded(scale: options.scaleFactor)
                             sSelf.storeImage(result!, forKey: key, toDisk: false, completionHandler: nil)
                             sSelf.storeImage(result!, forKey: key, toDisk: false, completionHandler: nil)
 
 
-                            dispatch_async_safely_to_queue(options.callbackDispatchQueue, { () -> Void in
+                            options.callbackDispatchQueue.safeAsync {
                                 completionHandler(result, .memory)
                                 completionHandler(result, .memory)
                                 sSelf = nil
                                 sSelf = nil
-                            })
+                            }
                         })
                         })
                     } else {
                     } else {
                         sSelf.storeImage(image, forKey: key, toDisk: false, completionHandler: nil)
                         sSelf.storeImage(image, forKey: key, toDisk: false, completionHandler: nil)
-                        dispatch_async_safely_to_queue(options.callbackDispatchQueue, { () -> Void in
+                        options.callbackDispatchQueue.safeAsync {
                             completionHandler(image, .disk)
                             completionHandler(image, .disk)
                             sSelf = nil
                             sSelf = nil
-                        })
+                        }
                     }
                     }
                 } else {
                 } else {
                     // No image found from either memory or disk
                     // No image found from either memory or disk
-                    dispatch_async_safely_to_queue(options.callbackDispatchQueue, { () -> Void in
+                    options.callbackDispatchQueue.safeAsync {
                         completionHandler(nil, .none)
                         completionHandler(nil, .none)
                         sSelf = nil
                         sSelf = nil
-                    })
+                    }
                 }
                 }
             })
             })
             
             
@@ -523,7 +523,7 @@ extension ImageCache {
      - returns: True if the image is cached, false otherwise.
      - returns: True if the image is cached, false otherwise.
      */
      */
     public func cachedImageExists(for url: URL) -> Bool {
     public func cachedImageExists(for url: URL) -> Bool {
-        let resource = Resource(downloadURL: url)
+        let resource = ImageResource(downloadURL: url)
         let result = isImageCachedForKey(resource.cacheKey)
         let result = isImageCachedForKey(resource.cacheKey)
         return result.cached
         return result.cached
     }
     }

+ 2 - 2
Sources/ImageDownloader.swift

@@ -445,9 +445,9 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic
             downloader.clean(for: url)
             downloader.clean(for: url)
             
             
             for callbackPair in callbackPairs {
             for callbackPair in callbackPairs {
-                dispatch_async_safely_to_queue(options.callbackDispatchQueue, { () -> Void in
+                options.callbackDispatchQueue.safeAsync {
                     callbackPair.completionHander?(image: image, error: error, url: url, originalData: originalData)
                     callbackPair.completionHander?(image: image, error: error, url: url, originalData: originalData)
-                })
+                }
             }
             }
             
             
             if downloader.fetchLoads.isEmpty {
             if downloader.fetchLoads.isEmpty {

+ 11 - 11
Sources/ImagePrefetcher.swift

@@ -97,7 +97,7 @@ public class ImagePrefetcher {
                    progressBlock: PrefetcherProgressBlock? = nil,
                    progressBlock: PrefetcherProgressBlock? = nil,
                completionHandler: PrefetcherCompletionHandler? = nil)
                completionHandler: PrefetcherCompletionHandler? = nil)
     {
     {
-        let resources = urls.map { Resource(downloadURL: $0) }
+        let resources: [Resource] = urls.map { ImageResource(downloadURL: $0) }
         self.init(resources: resources, optionsInfo: optionsInfo, progressBlock: progressBlock, completionHandler: completionHandler)
         self.init(resources: resources, optionsInfo: optionsInfo, progressBlock: progressBlock, completionHandler: completionHandler)
     }
     }
     
     
@@ -146,7 +146,7 @@ public class ImagePrefetcher {
     public func start()
     public func start()
     {
     {
         // Since we want to handle the resources cancellation in main thread only.
         // Since we want to handle the resources cancellation in main thread only.
-        dispatch_async_safely_to_main_queue { () -> () in
+        DispatchQueue.main.safeAsync {
             
             
             guard !self.stopped else {
             guard !self.stopped else {
                 assertionFailure("You can not restart the same prefetcher. Try to create a new prefetcher.")
                 assertionFailure("You can not restart the same prefetcher. Try to create a new prefetcher.")
@@ -167,7 +167,7 @@ public class ImagePrefetcher {
             
             
             let initialConcurentDownloads = min(self.prefetchResources.count, self.maxConcurrentDownloads)
             let initialConcurentDownloads = min(self.prefetchResources.count, self.maxConcurrentDownloads)
             for i in 0 ..< initialConcurentDownloads {
             for i in 0 ..< initialConcurentDownloads {
-                self.startPrefetchingResource(self.prefetchResources[i])
+                self.startPrefetching(self.prefetchResources[i])
             }
             }
         }
         }
     }
     }
@@ -177,7 +177,7 @@ public class ImagePrefetcher {
      Stop current downloading progress, and cancel any future prefetching activity that might be occuring.
      Stop current downloading progress, and cancel any future prefetching activity that might be occuring.
      */
      */
     public func stop() {
     public func stop() {
-        dispatch_async_safely_to_main_queue {
+        DispatchQueue.main.safeAsync {
             
             
             if self.finished {
             if self.finished {
                 return
                 return
@@ -190,7 +190,7 @@ public class ImagePrefetcher {
         }
         }
     }
     }
     
     
-    func downloadAndCacheResource(_ resource: Resource) {
+    func downloadAndCache(_ resource: Resource) {
 
 
         let task = RetrieveImageTask()
         let task = RetrieveImageTask()
         let downloadTask = manager.downloadAndCacheImageWithURL(
         let downloadTask = manager.downloadAndCacheImageWithURL(
@@ -228,24 +228,24 @@ public class ImagePrefetcher {
         }
         }
     }
     }
     
     
-    func appendCachedResource(_ resource: Resource) {
+    func append(cached resource: Resource) {
         skippedResources.append(resource)
         skippedResources.append(resource)
  
  
         reportProgress()
         reportProgress()
         reportCompletionOrStartNext()
         reportCompletionOrStartNext()
     }
     }
     
     
-    func startPrefetchingResource(_ resource: Resource)
+    func startPrefetching(_ resource: Resource)
     {
     {
         requestedCount += 1
         requestedCount += 1
         if optionsInfo.forceRefresh {
         if optionsInfo.forceRefresh {
-            downloadAndCacheResource(resource)
+            downloadAndCache(resource)
         } else {
         } else {
             let alreadyInCache = manager.cache.isImageCachedForKey(resource.cacheKey).cached
             let alreadyInCache = manager.cache.isImageCachedForKey(resource.cacheKey).cached
             if alreadyInCache {
             if alreadyInCache {
-                appendCachedResource(resource)
+                append(cached: resource)
             } else {
             } else {
-                downloadAndCacheResource(resource)
+                downloadAndCache(resource)
             }
             }
         }
         }
     }
     }
@@ -259,7 +259,7 @@ public class ImagePrefetcher {
             handleComplete()
             handleComplete()
         } else {
         } else {
             if requestedCount < prefetchResources.count {
             if requestedCount < prefetchResources.count {
-                startPrefetchingResource(prefetchResources[requestedCount])
+                startPrefetching(prefetchResources[requestedCount])
             }
             }
         }
         }
     }
     }

+ 3 - 3
Sources/ImageView+Kingfisher.swift

@@ -56,13 +56,13 @@ extension ImageView {
      The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method.
      The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method.
      */
      */
     @discardableResult
     @discardableResult
-    public func kf_setImageWithURL(_ URL: Foundation.URL?,
+    public func kf_setImageWithURL(_ URL: URL?,
                                    placeholderImage: Image? = nil,
                                    placeholderImage: Image? = nil,
                                    optionsInfo: KingfisherOptionsInfo? = nil,
                                    optionsInfo: KingfisherOptionsInfo? = nil,
                                    progressBlock: DownloadProgressBlock? = nil,
                                    progressBlock: DownloadProgressBlock? = nil,
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
         return kf_setImageWithResource(resource,
                                        placeholderImage: placeholderImage,
                                        placeholderImage: placeholderImage,
                                        optionsInfo: optionsInfo,
                                        optionsInfo: optionsInfo,
@@ -122,7 +122,7 @@ extension ImageView {
             },
             },
             completionHandler: {[weak self] image, error, cacheType, imageURL in
             completionHandler: {[weak self] image, error, cacheType, imageURL in
                 
                 
-                dispatch_async_safely_to_main_queue {
+                DispatchQueue.main.safeAsync {
                     guard let sSelf = self, imageURL == sSelf.kf_webURL else {
                     guard let sSelf = self, imageURL == sSelf.kf_webURL else {
                         return
                         return
                     }
                     }

+ 2 - 2
Sources/KingfisherManager.swift

@@ -159,12 +159,12 @@ public class KingfisherManager {
     - returns: A `RetrieveImageTask` task object. You can use this object to cancel the task.
     - returns: A `RetrieveImageTask` task object. You can use this object to cancel the task.
     */
     */
     @discardableResult
     @discardableResult
-    public func retrieveImageWithURL(_ URL: Foundation.URL,
+    public func retrieveImageWithURL(_ URL: URL,
                              optionsInfo: KingfisherOptionsInfo?,
                              optionsInfo: KingfisherOptionsInfo?,
                            progressBlock: DownloadProgressBlock?,
                            progressBlock: DownloadProgressBlock?,
                        completionHandler: CompletionHandler?) -> RetrieveImageTask
                        completionHandler: CompletionHandler?) -> RetrieveImageTask
     {
     {
-        return retrieveImageWithResource(Resource(downloadURL: URL), optionsInfo: optionsInfo, progressBlock: progressBlock, completionHandler: completionHandler)
+        return retrieveImageWithResource(ImageResource(downloadURL: URL), optionsInfo: optionsInfo, progressBlock: progressBlock, completionHandler: completionHandler)
     }
     }
     
     
     @discardableResult
     @discardableResult

+ 4 - 4
Sources/NSButton+Kingfisher.swift

@@ -54,7 +54,7 @@ extension NSButton {
                                    progressBlock: DownloadProgressBlock? = nil,
                                    progressBlock: DownloadProgressBlock? = nil,
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
         return kf_setImageWithResource(resource,
                                        placeholderImage: placeholderImage,
                                        placeholderImage: placeholderImage,
                                        optionsInfo: optionsInfo,
                                        optionsInfo: optionsInfo,
@@ -99,7 +99,7 @@ extension NSButton {
                 }
                 }
             },
             },
              completionHandler: {[weak self] image, error, cacheType, imageURL in
              completionHandler: {[weak self] image, error, cacheType, imageURL in
-                dispatch_async_safely_to_main_queue {
+                DispatchQueue.main.safeAsync {
                     guard let sSelf = self, imageURL == sSelf.kf_webURL else {
                     guard let sSelf = self, imageURL == sSelf.kf_webURL else {
                         return
                         return
                     }
                     }
@@ -170,7 +170,7 @@ extension NSButton {
                                             progressBlock: DownloadProgressBlock? = nil,
                                             progressBlock: DownloadProgressBlock? = nil,
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setAlternateImageWithResource(resource,
         return kf_setAlternateImageWithResource(resource,
                                                 placeholderImage: placeholderImage,
                                                 placeholderImage: placeholderImage,
                                                 optionsInfo: optionsInfo,
                                                 optionsInfo: optionsInfo,
@@ -215,7 +215,7 @@ extension NSButton {
                 }
                 }
             },
             },
              completionHandler: {[weak self] image, error, cacheType, imageURL in
              completionHandler: {[weak self] image, error, cacheType, imageURL in
-                dispatch_async_safely_to_main_queue {
+                DispatchQueue.main.safeAsync {
                     guard let sSelf = self, imageURL == sSelf.kf_alternateWebURL else {
                     guard let sSelf = self, imageURL == sSelf.kf_alternateWebURL else {
                         return
                         return
                     }
                     }

+ 10 - 2
Sources/Resource.swift

@@ -26,13 +26,21 @@
 
 
 import Foundation
 import Foundation
 
 
+public protocol Resource {
+    /// The key used in cache.
+    var cacheKey: String { get }
+    
+    /// The target image URL.
+    var downloadURL: URL { get }
+}
+
 /**
 /**
- Resource is a simple combination of `downloadURL` and `cacheKey`.
+ ImageResource is a simple combination of `downloadURL` and `cacheKey`.
  
  
  When passed to image view set methods, Kingfisher will try to download the target 
  When passed to image view set methods, Kingfisher will try to download the target 
  image from the `downloadURL`, and then store it with the `cacheKey` as the key in cache.
  image from the `downloadURL`, and then store it with the `cacheKey` as the key in cache.
  */
  */
-public struct Resource {
+public struct ImageResource: Resource {
     /// The key used in cache.
     /// The key used in cache.
     public let cacheKey: String
     public let cacheKey: String
     
     

+ 8 - 12
Sources/ThreadHelper.swift

@@ -26,19 +26,15 @@
 
 
 import Foundation
 import Foundation
 
 
-func dispatch_async_safely_to_main_queue(_ block: ()->()) {
-    dispatch_async_safely_to_queue(DispatchQueue.main, block)
-}
-
-// This method will dispatch the `block` to a specified `queue`.
-// If the `queue` is the main queue, and current thread is main thread, the block 
-// will be invoked immediately instead of being dispatched.
-func dispatch_async_safely_to_queue(_ queue: DispatchQueue, _ block: ()->()) {
-    if queue === DispatchQueue.main && Thread.isMainThread {
-        block()
-    } else {
-        queue.async {
+extension DispatchQueue {
+    // This method will dispatch the `block` to self.
+    // If `self` is the main queue, and current thread is main thread, the block
+    // will be invoked immediately instead of being dispatched.
+    func safeAsync(_ block: ()->()) {
+        if self === DispatchQueue.main && Thread.isMainThread {
             block()
             block()
+        } else {
+            async { block() }
         }
         }
     }
     }
 }
 }

+ 5 - 5
Sources/UIButton+Kingfisher.swift

@@ -53,7 +53,7 @@ extension UIButton {
                                             progressBlock: DownloadProgressBlock? = nil,
                                             progressBlock: DownloadProgressBlock? = nil,
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
         return kf_setImageWithResource(resource,
                                        forState: state,
                                        forState: state,
                                        placeholderImage: placeholderImage,
                                        placeholderImage: placeholderImage,
@@ -101,7 +101,7 @@ extension UIButton {
                 }
                 }
             },
             },
             completionHandler: {[weak self] image, error, cacheType, imageURL in
             completionHandler: {[weak self] image, error, cacheType, imageURL in
-                dispatch_async_safely_to_main_queue {
+                DispatchQueue.main.safeAsync {
                     guard let sSelf = self, imageURL == sSelf.kf_webURLForState(state) else {
                     guard let sSelf = self, imageURL == sSelf.kf_webURLForState(state) else {
                         return
                         return
                     }
                     }
@@ -191,7 +191,7 @@ extension UIButton {
                                                       progressBlock: DownloadProgressBlock? = nil,
                                                       progressBlock: DownloadProgressBlock? = nil,
                                                       completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
                                                       completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setBackgroundImageWithResource(resource,
         return kf_setBackgroundImageWithResource(resource,
                                                  forState: state,
                                                  forState: state,
                                                  placeholderImage: placeholderImage,
                                                  placeholderImage: placeholderImage,
@@ -229,7 +229,7 @@ extension UIButton {
         
         
         guard let resource = resource else {
         guard let resource = resource else {
             completionHandler?(image: nil, error: nil, cacheType: .none, imageURL: nil)
             completionHandler?(image: nil, error: nil, cacheType: .none, imageURL: nil)
-            return RetrieveImageTask.emptyTask
+            return .emptyTask
         }
         }
         
         
         kf_setBackgroundWebURL(resource.downloadURL as URL, forState: state)
         kf_setBackgroundWebURL(resource.downloadURL as URL, forState: state)
@@ -240,7 +240,7 @@ extension UIButton {
                 }
                 }
             },
             },
             completionHandler: { [weak self] image, error, cacheType, imageURL in
             completionHandler: { [weak self] image, error, cacheType, imageURL in
-                dispatch_async_safely_to_main_queue {
+                DispatchQueue.main.safeAsync {
                     guard let sSelf = self, imageURL == sSelf.kf_backgroundWebURLForState(state) else {
                     guard let sSelf = self, imageURL == sSelf.kf_backgroundWebURLForState(state) else {
                         return
                         return
                     }
                     }

+ 1 - 1
Tests/KingfisherTests/ImageViewExtensionTests.swift

@@ -111,7 +111,7 @@ class ImageViewExtensionTests: XCTestCase {
         let URLString = testKeys[0]
         let URLString = testKeys[0]
         _ = stubRequest("GET", URLString).andReturn(200)?.withBody(testImageData)
         _ = stubRequest("GET", URLString).andReturn(200)?.withBody(testImageData)
         let URL = Foundation.URL(string: URLString)!
         let URL = Foundation.URL(string: URLString)!
-        let resource = Resource(downloadURL: URL)
+        let resource = ImageResource(downloadURL: URL)
         
         
         var progressBlockIsCalled = false
         var progressBlockIsCalled = false