onevcat 8 лет назад
Родитель
Сommit
aa75cf42c3

+ 8 - 0
Sources/ImageProcessor.swift

@@ -87,6 +87,14 @@ public extension ImageProcessor {
     }
 }
 
+func ==(left: ImageProcessor, right: ImageProcessor) -> Bool {
+    return left.identifier == right.identifier
+}
+
+func !=(left: ImageProcessor, right: ImageProcessor) -> Bool {
+    return !(left == right)
+}
+
 fileprivate struct GeneralProcessor: ImageProcessor {
     let identifier: String
     let p: ProcessorImp

+ 53 - 16
Sources/KingfisherManager.swift

@@ -176,6 +176,19 @@ public class KingfisherManager {
                                       cacheSerializer: options.cacheSerializer,
                                       toDisk: !options.cacheMemoryOnly,
                                       completionHandler: nil)
+                    if options.cacheOriginalImage {
+                        let defaultProcessor = DefaultImageProcessor.default
+                        if let originaliImage = defaultProcessor.process(item: .data(originalData), options: options) {
+                            targetCache.store(originaliImage,
+                                              original: originalData,
+                                              forKey: key,
+                                              processorIdentifier: defaultProcessor.identifier,
+                                              cacheSerializer: options.cacheSerializer,
+                                              toDisk: !options.cacheMemoryOnly,
+                                              completionHandler: nil)
+                        }
+                        
+                    }
                 }
 
                 completionHandler?(image, error, .none, url)
@@ -190,28 +203,52 @@ public class KingfisherManager {
                               completionHandler: CompletionHandler?,
                                         options: KingfisherOptionsInfo)
     {
+        
+        
         let diskTaskCompletionHandler: CompletionHandler = { (image, error, cacheType, imageURL) -> () in
             completionHandler?(image, error, cacheType, imageURL)
         }
         
         let targetCache = options.targetCache
-        targetCache.retrieveImage(forKey: key, options: options,
-            completionHandler: { image, cacheType in
-                if image != nil {
-                    diskTaskCompletionHandler(image, nil, cacheType, url)
-                } else if options.onlyFromCache {
-                    let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil)
-                    diskTaskCompletionHandler(nil, error, .none, url)
-                } else {
-                    self.downloadAndCacheImage(
-                        with: url,
-                        forKey: key,
-                        retrieveImageTask: retrieveImageTask,
-                        progressBlock: progressBlock,
-                        completionHandler: diskTaskCompletionHandler,
-                        options: options)
+        targetCache.retrieveImage(forKey: key, options: options) { image, cacheType in
+            if image != nil {
+                diskTaskCompletionHandler(image, nil, cacheType, url)
+                return
+            }
+            
+            let processor = options.processor
+            if processor != DefaultImageProcessor.default {
+                let optionsWithoutProcessor = options.removeAllMatchesIgnoringAssociatedValue(.processor(processor))
+                targetCache.retrieveImage(forKey: key, options: optionsWithoutProcessor) { image, cacheType in
+                    guard let image = image else {
+                        handleNoCache()
+                        return
+                    }
+                    
+                    let processedImage = processor.process(item: .image(image), options: options)
+                    diskTaskCompletionHandler(processedImage, nil, .none, url)
+                    return
                 }
+                return
+            }
+            
+            handleNoCache()
+        }
+        
+        func handleNoCache() {
+            if options.onlyFromCache {
+                let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil)
+                diskTaskCompletionHandler(nil, error, .none, url)
+                return
             }
-        )
+            self.downloadAndCacheImage(
+                with: url,
+                forKey: key,
+                retrieveImageTask: retrieveImageTask,
+                progressBlock: progressBlock,
+                completionHandler: diskTaskCompletionHandler,
+                options: options)
+            
+        }
     }
 }

+ 11 - 0
Sources/KingfisherOptionsInfo.swift

@@ -119,6 +119,12 @@ public enum KingfisherOptionsInfoItem {
     /// static preview of the first frame from a animated image.
     /// This option will be ignored if the target image is not animated image data.
     case onlyLoadFirstFrame
+    
+    /// If set and an `ImageProcessor` is used, Kingfisher will try to cache both 
+    /// the final result and original image. Kingfisher will have a chance to use 
+    /// the original image when another processor is applied to the same resouce, 
+    /// instead of downloading it again.
+    case cacheOriginalImage
 }
 
 precedencegroup ItemComparisonPrecedence {
@@ -148,6 +154,7 @@ func <== (lhs: KingfisherOptionsInfoItem, rhs: KingfisherOptionsInfoItem) -> Boo
     case (.cacheSerializer(_), .cacheSerializer(_)): return true
     case (.keepCurrentImageWhileLoading, .keepCurrentImageWhileLoading): return true
     case (.onlyLoadFirstFrame, .onlyLoadFirstFrame): return true
+    case (.cacheOriginalImage, .cacheOriginalImage): return true
     default: return false
     }
 }
@@ -294,6 +301,10 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem
     public var onlyLoadFirstFrame: Bool {
         return contains { $0 <== .onlyLoadFirstFrame }
     }
+    
+    public var cacheOriginalImage: Bool {
+        return contains { $0 <== .cacheOriginalImage }
+    }
 }
 
 // MARK: - Deprecated. Only for back compatibility.

+ 4 - 1
Tests/KingfisherTests/KingfisherOptionsInfoTests.swift

@@ -60,6 +60,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         XCTAssertEqual(options.scaleFactor, 1.0)
         XCTAssertFalse(options.keepCurrentImageWhileLoading)
         XCTAssertFalse(options.onlyLoadFirstFrame)
+        XCTAssertFalse(options.cacheOriginalImage)
     }
     
 
@@ -91,7 +92,8 @@ class KingfisherOptionsInfoTests: XCTestCase {
             .requestModifier(testModifier),
             .processor(processor),
             .keepCurrentImageWhileLoading,
-            .onlyLoadFirstFrame
+            .onlyLoadFirstFrame,
+            .cacheOriginalImage
         ]
         
         XCTAssertTrue(options.targetCache === cache)
@@ -116,6 +118,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         XCTAssertEqual(options.processor.identifier, processor.identifier)
         XCTAssertTrue(options.keepCurrentImageWhileLoading)
         XCTAssertTrue(options.onlyLoadFirstFrame)
+        XCTAssertTrue(options.cacheOriginalImage)
     }
     
     func testOptionCouldBeOverwritten() {