Ver código fonte

Add cancel API on image view for an easier use

onevcat 10 anos atrás
pai
commit
bd8facb4db

+ 4 - 0
Kingfisher-Demo/ViewController.swift

@@ -55,6 +55,10 @@ extension ViewController {
         return 10
     }
     
+    override func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
+        (cell as! CollectionViewCell).cellImageView.kf_cancelDownloadTask()
+    }
+    
     override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
         // swiftlint:disable force_cast
         let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionViewCell", forIndexPath: indexPath) as! CollectionViewCell

+ 36 - 10
Kingfisher/UIImageView+Kingfisher.swift

@@ -187,6 +187,7 @@ public extension UIImageView {
         image = placeholderImage
         
         kf_setWebURL(resource.downloadURL)
+        
         let task = KingfisherManager.sharedManager.retrieveImageWithResource(resource, optionsInfo: optionsInfo,
             progressBlock: { receivedSize, totalSize in
                 if let progressBlock = progressBlock {
@@ -199,10 +200,21 @@ public extension UIImageView {
             completionHandler: {[weak self] image, error, cacheType, imageURL in
                 
                 dispatch_async_safely_main_queue {
-                    if let sSelf = self where imageURL == sSelf.kf_webURL && image != nil {
-                        
-                        if let transitionItem = optionsInfo?.kf_firstMatchIgnoringAssociatedValue(.Transition(.None)),
-                            case .Transition(let transition) = transitionItem where cacheType == .None {
+                    
+                    guard let sSelf = self where imageURL == sSelf.kf_webURL else {
+                        completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
+                        return
+                    }
+                    
+                    sSelf.kf_setImageTask(nil)
+                    
+                    guard let image = image else {
+                        completionHandler?(image: nil, error: error, cacheType: cacheType, imageURL: imageURL)
+                        return
+                    }
+                    
+                    if let transitionItem = optionsInfo?.kf_firstMatchIgnoringAssociatedValue(.Transition(.None)),
+                        case .Transition(let transition) = transitionItem where cacheType == .None {
                             
                             UIView.transitionWithView(sSelf, duration: 0.0, options: [],
                                 animations: {
@@ -212,7 +224,7 @@ public extension UIImageView {
                                     UIView.transitionWithView(sSelf, duration: transition.duration,
                                         options: transition.animationOptions,
                                         animations: {
-                                            transition.animations?(sSelf, image!)
+                                            transition.animations?(sSelf, image)
                                         },
                                         completion: { finished in
                                             transition.completion?(finished)
@@ -221,18 +233,17 @@ public extension UIImageView {
                                     )
                                 }
                             )
-                        } else {
-                            indicator?.stopAnimating()
-                            sSelf.image = image
-                            completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
-                        }
                     } else {
+                        indicator?.stopAnimating()
+                        sSelf.image = image
                         completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
                     }
                 }
             }
         )
         
+        kf_setImageTask(task)
+        
         return task
     }
     
@@ -262,10 +273,17 @@ public extension UIImageView {
     }
 }
 
+extension UIImageView {
+    public func kf_cancelDownloadTask() {
+        kf_imageTask?.downloadTask?.cancel()
+    }
+}
+
 // MARK: - Associated Object
 private var lastURLKey: Void?
 private var indicatorKey: Void?
 private var showIndicatorWhenLoadingKey: Void?
+private var imageTaskKey: Void?
 
 public extension UIImageView {
     /// Get the image URL binded to this image view.
@@ -327,6 +345,14 @@ public extension UIImageView {
     private func kf_setIndicator(indicator: UIActivityIndicatorView?) {
         objc_setAssociatedObject(self, &indicatorKey, indicator, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
     }
+    
+    private var kf_imageTask: RetrieveImageTask? {
+        return objc_getAssociatedObject(self, &imageTaskKey) as? RetrieveImageTask
+    }
+    
+    private func kf_setImageTask(task: RetrieveImageTask?) {
+        objc_setAssociatedObject(self, &imageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+    }
 }
 
 // MARK: - Deprecated

+ 24 - 0
KingfisherTests/UIImageViewExtensionTests.swift

@@ -387,4 +387,28 @@ class UIImageViewExtensionTests: XCTestCase {
         
         waitForExpectationsWithTimeout(5, handler: nil)
     }
+    
+    func testCacnelImageTask() {
+        let expectation = expectationWithDescription("wait for downloading image")
+        
+        let URLString = testKeys[0]
+        let stub = stubRequest("GET", URLString).andReturn(200).withBody(testImageData).delay()
+        let URL = NSURL(string: URLString)!
+        
+        imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
+                XCTFail("Progress block should not be called.")
+            }) { (image, error, cacheType, imageURL) -> () in
+                XCTAssertNotNil(error)
+                XCTAssertEqual(error?.code, NSURLErrorCancelled)
+                
+                expectation.fulfill()
+        }
+        
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
+            self.imageView.kf_cancelDownloadTask()
+            stub.go()
+        }
+        
+        waitForExpectationsWithTimeout(5, handler: nil)
+    }
 }