Browse Source

Refactor for ImagePrefetcher

onevcat 9 years ago
parent
commit
f95cbc4b51

+ 8 - 8
Sources/ImageCache.swift

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

+ 2 - 2
Sources/ImageDownloader.swift

@@ -445,9 +445,9 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic
             downloader.clean(for: url)
             
             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)
-                })
+                }
             }
             
             if downloader.fetchLoads.isEmpty {

+ 11 - 11
Sources/ImagePrefetcher.swift

@@ -97,7 +97,7 @@ public class ImagePrefetcher {
                    progressBlock: PrefetcherProgressBlock? = 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)
     }
     
@@ -146,7 +146,7 @@ public class ImagePrefetcher {
     public func start()
     {
         // 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 {
                 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)
             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.
      */
     public func stop() {
-        dispatch_async_safely_to_main_queue {
+        DispatchQueue.main.safeAsync {
             
             if self.finished {
                 return
@@ -190,7 +190,7 @@ public class ImagePrefetcher {
         }
     }
     
-    func downloadAndCacheResource(_ resource: Resource) {
+    func downloadAndCache(_ resource: Resource) {
 
         let task = RetrieveImageTask()
         let downloadTask = manager.downloadAndCacheImageWithURL(
@@ -228,24 +228,24 @@ public class ImagePrefetcher {
         }
     }
     
-    func appendCachedResource(_ resource: Resource) {
+    func append(cached resource: Resource) {
         skippedResources.append(resource)
  
         reportProgress()
         reportCompletionOrStartNext()
     }
     
-    func startPrefetchingResource(_ resource: Resource)
+    func startPrefetching(_ resource: Resource)
     {
         requestedCount += 1
         if optionsInfo.forceRefresh {
-            downloadAndCacheResource(resource)
+            downloadAndCache(resource)
         } else {
             let alreadyInCache = manager.cache.isImageCachedForKey(resource.cacheKey).cached
             if alreadyInCache {
-                appendCachedResource(resource)
+                append(cached: resource)
             } else {
-                downloadAndCacheResource(resource)
+                downloadAndCache(resource)
             }
         }
     }
@@ -259,7 +259,7 @@ public class ImagePrefetcher {
             handleComplete()
         } else {
             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.
      */
     @discardableResult
-    public func kf_setImageWithURL(_ URL: Foundation.URL?,
+    public func kf_setImageWithURL(_ URL: URL?,
                                    placeholderImage: Image? = nil,
                                    optionsInfo: KingfisherOptionsInfo? = nil,
                                    progressBlock: DownloadProgressBlock? = nil,
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
                                        placeholderImage: placeholderImage,
                                        optionsInfo: optionsInfo,
@@ -122,7 +122,7 @@ extension ImageView {
             },
             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 {
                         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.
     */
     @discardableResult
-    public func retrieveImageWithURL(_ URL: Foundation.URL,
+    public func retrieveImageWithURL(_ URL: URL,
                              optionsInfo: KingfisherOptionsInfo?,
                            progressBlock: DownloadProgressBlock?,
                        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

+ 4 - 4
Sources/NSButton+Kingfisher.swift

@@ -54,7 +54,7 @@ extension NSButton {
                                    progressBlock: DownloadProgressBlock? = nil,
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
                                        placeholderImage: placeholderImage,
                                        optionsInfo: optionsInfo,
@@ -99,7 +99,7 @@ extension NSButton {
                 }
             },
              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 {
                         return
                     }
@@ -170,7 +170,7 @@ extension NSButton {
                                             progressBlock: DownloadProgressBlock? = nil,
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setAlternateImageWithResource(resource,
                                                 placeholderImage: placeholderImage,
                                                 optionsInfo: optionsInfo,
@@ -215,7 +215,7 @@ extension NSButton {
                 }
             },
              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 {
                         return
                     }

+ 10 - 2
Sources/Resource.swift

@@ -26,13 +26,21 @@
 
 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 
  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.
     public let cacheKey: String
     

+ 8 - 12
Sources/ThreadHelper.swift

@@ -26,19 +26,15 @@
 
 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()
+        } else {
+            async { block() }
         }
     }
 }

+ 5 - 5
Sources/UIButton+Kingfisher.swift

@@ -53,7 +53,7 @@ extension UIButton {
                                             progressBlock: DownloadProgressBlock? = nil,
                                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setImageWithResource(resource,
                                        forState: state,
                                        placeholderImage: placeholderImage,
@@ -101,7 +101,7 @@ extension UIButton {
                 }
             },
             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 {
                         return
                     }
@@ -191,7 +191,7 @@ extension UIButton {
                                                       progressBlock: DownloadProgressBlock? = nil,
                                                       completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        let resource = URL.map { Resource(downloadURL: $0) }
+        let resource = URL.map { ImageResource(downloadURL: $0) }
         return kf_setBackgroundImageWithResource(resource,
                                                  forState: state,
                                                  placeholderImage: placeholderImage,
@@ -229,7 +229,7 @@ extension UIButton {
         
         guard let resource = resource else {
             completionHandler?(image: nil, error: nil, cacheType: .none, imageURL: nil)
-            return RetrieveImageTask.emptyTask
+            return .emptyTask
         }
         
         kf_setBackgroundWebURL(resource.downloadURL as URL, forState: state)
@@ -240,7 +240,7 @@ extension UIButton {
                 }
             },
             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 {
                         return
                     }

+ 1 - 1
Tests/KingfisherTests/ImageViewExtensionTests.swift

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