2
0
Эх сурвалжийг харах

Merge pull request #1986 from onevcat/feature/data-reader

A data reader in `RetrieveImageResult`
Wei Wang 3 жил өмнө
parent
commit
a7e535feee

+ 19 - 5
Sources/General/KingfisherManager.swift

@@ -35,7 +35,6 @@ public typealias DownloadProgressBlock = ((_ receivedSize: Int64, _ totalSize: I
 
 /// Represents the result of a Kingfisher retrieving image task.
 public struct RetrieveImageResult {
-
     /// Gets the image object of this result.
     public let image: KFCrossPlatformImage
 
@@ -50,6 +49,17 @@ public struct RetrieveImageResult {
     /// When an alternative source loading happened, the `source` will be the replacing loading target, while the
     /// `originalSource` will be kept as the initial `source` which issued the image loading process.
     public let originalSource: Source
+    
+    /// Gets the data behind the result.
+    ///
+    /// If this result is from a network downloading (when `cacheType == .none`), calling this returns the downloaded
+    /// data. If the reuslt is from cache, it serializes the image with the given cache serializer in the loading option
+    /// and returns the result.
+    ///
+    /// - Note:
+    /// This can be a time-consuming action, so if you need to use the data for multiple times, it is suggested to hold
+    /// it and prevent keeping calling this too frequently.
+    public let data: () -> Data?
 }
 
 /// A struct that stores some related information of an `KingfisherError`. It provides some context information for
@@ -419,7 +429,8 @@ public class KingfisherManager {
                 image: options.imageModifier?.modify(value.image) ?? value.image,
                 cacheType: .none,
                 source: source,
-                originalSource: context.originalSource
+                originalSource: context.originalSource,
+                data: {  value.originalData }
             )
             // Add image to cache.
             let targetCache = options.targetCache ?? self.cache
@@ -561,7 +572,8 @@ public class KingfisherManager {
                                         image: image,
                                         cacheType: $0.cacheType,
                                         source: source,
-                                        originalSource: context.originalSource
+                                        originalSource: context.originalSource,
+                                        data: { options.cacheSerializer.data(with: image, original: nil) }
                                     )
                                 }
                             } else {
@@ -624,11 +636,13 @@ public class KingfisherManager {
                             let coordinator = CacheCallbackCoordinator(
                                 shouldWaitForCache: options.waitForCache, shouldCacheOriginal: false)
 
+                            let image = options.imageModifier?.modify(processedImage) ?? processedImage
                             let result = RetrieveImageResult(
-                                image: options.imageModifier?.modify(processedImage) ?? processedImage,
+                                image: image,
                                 cacheType: .none,
                                 source: source,
-                                originalSource: context.originalSource
+                                originalSource: context.originalSource,
+                                data: { options.cacheSerializer.data(with: processedImage, original: nil) }
                             )
 
                             targetCache.store(

+ 56 - 0
Tests/KingfisherTests/KingfisherManagerTests.swift

@@ -1073,6 +1073,62 @@ class KingfisherManagerTests: XCTestCase {
             }
         waitForExpectations(timeout: 1.0)
     }
+    
+    func testImageResultContainsDataWhenDownloaded() {
+        let exp = expectation(description: #function)
+        let url = testURLs[0]
+        stub(url, data: testImageData)
+        
+        manager.retrieveImage(with: url) { result in
+            XCTAssertNotNil(result.value?.data())
+            XCTAssertEqual(result.value!.data(), testImageData)
+            XCTAssertEqual(result.value!.cacheType, .none)
+            exp.fulfill()
+        }
+        
+        waitForExpectations(timeout: 3, handler: nil)
+    }
+    
+    func testImageResultContainsDataWhenLoadFromMemoryCache() {
+        let exp = expectation(description: #function)
+        let url = testURLs[0]
+        stub(url, data: testImageData)
+
+        manager.retrieveImage(with: url) { _ in
+            self.manager.retrieveImage(with: url) { result in
+                XCTAssertEqual(result.value!.cacheType, .memory)
+                XCTAssertNotNil(result.value?.data())
+                XCTAssertEqual(
+                    result.value!.data(),
+                    DefaultCacheSerializer.default.data(with: result.value!.image, original: nil)
+                )
+                exp.fulfill()
+            }
+        }
+        
+        waitForExpectations(timeout: 3, handler: nil)
+    }
+    
+    func testImageResultContainsDataWhenLoadFromDiskCache() {
+        let exp = expectation(description: #function)
+        let url = testURLs[0]
+        stub(url, data: testImageData)
+
+        manager.retrieveImage(with: url) { _ in
+            self.manager.cache.clearMemoryCache()
+            self.manager.retrieveImage(with: url) { result in
+                XCTAssertEqual(result.value!.cacheType, .disk)
+                XCTAssertNotNil(result.value?.data())
+                XCTAssertEqual(
+                    result.value!.data(),
+                    DefaultCacheSerializer.default.data(with: result.value!.image, original: nil)
+                )
+                exp.fulfill()
+            }
+        }
+        
+        waitForExpectations(timeout: 3, handler: nil)
+    }
 }
 
 class SimpleProcessor: ImageProcessor {