Kaynağa Gözat

Add apply condition to data receive side effect

onevcat 6 yıl önce
ebeveyn
işleme
48d55cc830

+ 22 - 38
Sources/Extensions/ImageView+Kingfisher.swift

@@ -104,28 +104,14 @@ extension KingfisherWrapper where Base: ImageView {
         if base.shouldPreloadAllAnimation() {
             options.preloadAllAnimationData = true
         }
-        
-        let progressive = ImageProgressiveProvider(
-            options,
-            isContinue: { () -> Bool in
-                issuedIdentifier == self.taskIdentifier
-            },
-            isFinished: { () -> Bool in
-                mutatingSelf.imageTask == nil
-            },
-            refreshImage: { (image) in
-                self.base.image = image
-            }
-        )
-        
+
+        options.onDataReceived?.forEach {
+            $0.onShouldApply = { issuedIdentifier == self.taskIdentifier }
+        }
+
         let task = KingfisherManager.shared.retrieveImage(
             with: source,
             options: options,
-            receivedBlock: { latest, received in
-                guard issuedIdentifier == self.taskIdentifier else { return }
-                let callbacks = mutatingSelf.imageTask?.sessionTask.callbacks ?? []
-                progressive.update(data: received, with: callbacks)
-            },
             progressBlock: { receivedSize, totalSize in
                 guard issuedIdentifier == self.taskIdentifier else { return }
                 progressBlock?(receivedSize, totalSize)
@@ -147,27 +133,25 @@ extension KingfisherWrapper where Base: ImageView {
                     }
                     
                     mutatingSelf.imageTask = nil
-                    
-                    progressive.finished {
-                        switch result {
-                        case .success(let value):
-                            guard self.needsTransition(options: options, cacheType: value.cacheType) else {
-                                mutatingSelf.placeholder = nil
-                                self.base.image = value.image
-                                completionHandler?(result)
-                                return
-                            }
-                            
-                            self.makeTransition(image: value.image, transition: options.transition) {
-                                completionHandler?(result)
-                            }
-                            
-                        case .failure:
-                            if let image = options.onFailureImage {
-                                self.base.image = image
-                            }
+
+                    switch result {
+                    case .success(let value):
+                        guard self.needsTransition(options: options, cacheType: value.cacheType) else {
+                            mutatingSelf.placeholder = nil
+                            self.base.image = value.image
                             completionHandler?(result)
+                            return
+                        }
+
+                        self.makeTransition(image: value.image, transition: options.transition) {
+                            completionHandler?(result)
+                        }
+
+                    case .failure:
+                        if let image = options.onFailureImage {
+                            self.base.image = image
                         }
+                        completionHandler?(result)
                     }
                 }
             }

+ 33 - 5
Sources/General/KingfisherOptionsInfo.swift

@@ -220,11 +220,6 @@ public enum KingfisherOptionsInfoItem {
     case onDataReceived([DataReceivingSideEffect])
 }
 
-
-public protocol DataReceivingSideEffect {
-    func onDataReceived(_ latest: Data, allData: Data)
-}
-
 // Improve performance by parsing the input `KingfisherOptionsInfo` (self) first.
 // So we can prevent the iterating over the options array again and again.
 /// The parsed options info used across Kingfisher methods. Each property in this type corresponds a case member
@@ -319,3 +314,36 @@ extension KingfisherParsedOptionsInfo {
             onlyFirstFrame: onlyLoadFirstFrame)
     }
 }
+
+public protocol DataReceivingSideEffect: AnyObject {
+    func onDataReceived(_ session: URLSession, task: SessionDataTask, data: Data)
+    var onShouldApply: () -> Bool { get set }
+}
+
+class ImageLoadingProgressSideEffect: DataReceivingSideEffect {
+
+    var onShouldApply: () -> Bool = { return true }
+
+
+    let block: DownloadProgressBlock
+
+    init(_ block: @escaping DownloadProgressBlock) {
+        self.block = block
+    }
+
+    func onDataReceived(_ session: URLSession, task: SessionDataTask, data: Data) {
+
+        guard onShouldApply() else { return }
+
+        guard let expectedContentLength = task.task.response?.expectedContentLength,
+                  expectedContentLength != -1 else
+        {
+            return
+        }
+
+        let dataLength = Int64(task.mutableData.count)
+        DispatchQueue.main.async {
+            self.block(dataLength, expectedContentLength)
+        }
+    }
+}

+ 4 - 5
Sources/Networking/SessionDelegate.swift

@@ -175,11 +175,10 @@ extension SessionDelegate: URLSessionDataDelegate {
                 }
             }
         }
-        
-        let received = task.mutableData
-        DispatchQueue.main.async {
-            task.callbacks.forEach { callback in
-                callback.onReceived?.call((data, received))
+
+        task.callbacks.forEach { callback in
+            callback.options.onDataReceived?.forEach { sideEffect in
+                sideEffect.onDataReceived(session, task: task, data: data)
             }
         }
     }

+ 31 - 6
Tests/KingfisherTests/DataReceivingSideEffectTests.swift

@@ -53,18 +53,43 @@ class DataReceivingSideEffectTests: XCTestCase {
         waitForExpectations(timeout: 3, handler: nil)
     }
 
-    func testPerformanceExample() {
-        // This is an example of a performance test case.
-        self.measure {
-            // Put the code you want to measure the time of here.
+    func testDataReceivingSideEffectBlockCanBeCalledButNotApply() {
+        let exp = expectation(description: #function)
+        let url = testURLs[0]
+        stub(url, data: testImageData)
+
+        let receiver = DataReceivingNotAppyStub()
+
+        let options: KingfisherOptionsInfo = [.onDataReceived([receiver])]
+        KingfisherManager.shared.retrieveImage(with: url, options: options) {
+            result in
+            XCTAssertTrue(receiver.called)
+            XCTAssertFalse(receiver.appied)
+            exp.fulfill()
         }
+        waitForExpectations(timeout: 3, handler: nil)
     }
-
 }
 
 class DataReceivingStub: DataReceivingSideEffect {
     var called: Bool = false
-    func onDataReceived(_ latest: Data, allData: Data) {
+    var onShouldApply: () -> Bool = { return true }
+    func onDataReceived(_ session: URLSession, task: SessionDataTask, data: Data) {
+        called = true
+    }
+}
+
+class DataReceivingNotAppyStub: DataReceivingSideEffect {
+
+    var called: Bool = false
+    var appied: Bool = false
+
+    var onShouldApply: () -> Bool = { return false }
+
+    func onDataReceived(_ session: URLSession, task: SessionDataTask, data: Data) {
         called = true
+        if onShouldApply() {
+            appied = true
+        }
     }
 }