Browse Source

Merge pull request #503 from onevcat/feature/keep-current-image-option

Add an option to keep current image while loading
Wei Wang 9 years ago
parent
commit
563b197e22

+ 7 - 4
Sources/ImageView+Kingfisher.swift

@@ -57,19 +57,22 @@ extension Kingfisher where Base: ImageView {
                          progressBlock: DownloadProgressBlock? = nil,
                          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        base.image = placeholder
-        
         guard let resource = resource else {
             completionHandler?(nil, nil, .none, nil)
             return .empty
         }
         
+        var options = options ?? KingfisherEmptyOptionsInfo
+        
+        if !options.keepCurrentImageWhileLoading {
+            base.image = placeholder
+        }
+
         let maybeIndicator = indicator
         maybeIndicator?.startAnimatingView()
         
         setWebURL(resource.downloadURL)
-        
-        var options = options ?? KingfisherEmptyOptionsInfo
+
         if shouldPreloadAllGIF() {
             options.append(.preloadAllGIFData)
         }

+ 10 - 0
Sources/KingfisherOptionsInfo.swift

@@ -106,6 +106,11 @@ public enum KingfisherOptionsInfoItem {
     /// retrieving from disk cache or vice versa for storing to disk cache.
     /// `DefaultCacheSerializer.default` will be used by default.
     case cacheSerializer(CacheSerializer)
+    
+    /// Keep the existing image while setting another image to an image view.
+    /// By setting this option, the placeholder image parameter of imageview extension method
+    /// will be ignored and the current image will be kept while loading or downloading the new image.
+    case keepCurrentImageWhileLoading
 }
 
 precedencegroup ItemComparisonPrecedence {
@@ -133,6 +138,7 @@ func <== (lhs: KingfisherOptionsInfoItem, rhs: KingfisherOptionsInfoItem) -> Boo
     case (.requestModifier(_), .requestModifier(_)): return true
     case (.processor(_), .processor(_)): return true
     case (.cacheSerializer(_), .cacheSerializer(_)): return true
+    case (.keepCurrentImageWhileLoading, .keepCurrentImageWhileLoading): return true
     default: return false
     }
 }
@@ -252,4 +258,8 @@ extension Collection where Iterator.Element == KingfisherOptionsInfoItem {
         }
         return DefaultCacheSerializer.default
     }
+    
+    var keepCurrentImageWhileLoading: Bool {
+        return contains { $0 <== .keepCurrentImageWhileLoading }
+    }
 }

+ 10 - 4
Sources/NSButton+Kingfisher.swift

@@ -53,13 +53,16 @@ extension Kingfisher where Base: NSButton {
                          progressBlock: DownloadProgressBlock? = nil,
                          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        base.image = placeholder
-        
         guard let resource = resource else {
             completionHandler?(nil, nil, .none, nil)
             return .empty
         }
         
+        let options = options ?? KingfisherEmptyOptionsInfo
+        if !options.keepCurrentImageWhileLoading {
+            base.image = placeholder
+        }
+        
         setWebURL(resource.downloadURL)
         let task = KingfisherManager.shared.retrieveImage(
             with: resource,
@@ -115,13 +118,16 @@ extension Kingfisher where Base: NSButton {
                                   progressBlock: DownloadProgressBlock? = nil,
                                   completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        base.alternateImage = placeholder
-        
         guard let resource = resource else {
             completionHandler?(nil, nil, .none, nil)
             return .empty
         }
         
+        let options = options ?? KingfisherEmptyOptionsInfo
+        if !options.keepCurrentImageWhileLoading {
+            base.alternateImage = placeholder
+        }
+        
         setAlternateWebURL(resource.downloadURL)
         let task = KingfisherManager.shared.retrieveImage(
             with: resource,

+ 10 - 4
Sources/UIButton+Kingfisher.swift

@@ -55,13 +55,16 @@ extension Kingfisher where Base: UIButton {
                          progressBlock: DownloadProgressBlock? = nil,
                          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        base.setImage(placeholder, for: state)
-        
         guard let resource = resource else {
             completionHandler?(nil, nil, .none, nil)
             return .empty
         }
         
+        let options = options ?? KingfisherEmptyOptionsInfo
+        if !options.keepCurrentImageWhileLoading {
+            base.setImage(placeholder, for: state)
+        }
+        
         setWebURL(resource.downloadURL, for: state)
         let task = KingfisherManager.shared.retrieveImage(
             with: resource,
@@ -122,13 +125,16 @@ extension Kingfisher where Base: UIButton {
                                    progressBlock: DownloadProgressBlock? = nil,
                                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
     {
-        base.setBackgroundImage(placeholder, for: state)
-        
         guard let resource = resource else {
             completionHandler?(nil, nil, .none, nil)
             return .empty
         }
         
+        let options = options ?? KingfisherEmptyOptionsInfo
+        if !options.keepCurrentImageWhileLoading {
+            base.setBackgroundImage(placeholder, for: state)
+        }
+        
         setBackgroundWebURL(resource.downloadURL, for: state)
         let task = KingfisherManager.shared.retrieveImage(
             with: resource,

+ 15 - 0
Tests/KingfisherTests/ImageViewExtensionTests.swift

@@ -525,4 +525,19 @@ class ImageViewExtensionTests: XCTestCase {
         
         waitForExpectations(timeout: 5, handler: nil)
     }
+    
+    func testSettingImageWhileKeepingCurrentOne() {
+
+        let URLString = testKeys[0]
+        _ = stubRequest("GET", URLString).andReturn(200)?.withBody(testImageData)
+        let url = URL(string: URLString)!
+        
+        imageView.image = testImage
+        imageView.kf.setImage(with: url, placeholder: nil, options: nil)
+        XCTAssertNil(imageView.image)
+        
+        imageView.image = testImage
+        imageView.kf.setImage(with: url, placeholder: nil, options: [.keepCurrentImageWhileLoading])
+        XCTAssertEqual(testImage, imageView.image)
+    }
 }

+ 4 - 1
Tests/KingfisherTests/KingfisherOptionsInfoTests.swift

@@ -58,6 +58,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         XCTAssertFalse(options.backgroundDecode)
         XCTAssertEqual(options.callbackDispatchQueue.label, DispatchQueue.main.label)
         XCTAssertEqual(options.scaleFactor, 1.0)
+        XCTAssertFalse(options.keepCurrentImageWhileLoading)
     }
     
 
@@ -87,7 +88,8 @@ class KingfisherOptionsInfoTests: XCTestCase {
             .callbackDispatchQueue(queue),
             KingfisherOptionsInfoItem.scaleFactor(2.0),
             .requestModifier(testModifier),
-            .processor(processor)
+            .processor(processor),
+            .keepCurrentImageWhileLoading
         ]
         
         XCTAssertTrue(options.targetCache === cache)
@@ -110,6 +112,7 @@ class KingfisherOptionsInfoTests: XCTestCase {
         XCTAssertEqual(options.scaleFactor, 2.0)
         XCTAssertTrue(options.modifier is TestModifier)
         XCTAssertEqual(options.processor.identifier, processor.identifier)
+        XCTAssertTrue(options.keepCurrentImageWhileLoading)
     }
 }