2
0
onevcat 5 жил өмнө
parent
commit
31bf6cb39f

+ 12 - 0
Sources/General/KFOptionsSetter.swift

@@ -321,6 +321,18 @@ extension KFOptionSetter {
         return self
     }
 
+    /// Sets the `Source` should be loaded when user enables Low Data Mode and the original source fails with an
+    /// `NSURLErrorNetworkUnavailableReason.constrained` error.
+    /// - Parameter source: The `Source` will be loaded under low data mode.
+    /// - Returns: A `Self` value with changes applied.
+    ///
+    /// When this option is set, the
+    /// `allowsConstrainedNetworkAccess` property of the request for the original source will be set to `false` and the
+    /// `Source` in associated value will be used to retrieve the image for low data mode. Usually, you can provide a
+    /// low-resolution version of your image or a local image provider to display a placeholder.
+    ///
+    /// If not set or the `source` is `nil`, the device Low Data Mode will be ignored and the original source will
+    /// be loaded following the system default behavior, in a normal way.
     public func lowDataModeSource(_ source: Source?) -> Self {
         options.lowDataModeSource = source
         return self

+ 9 - 2
Sources/General/KingfisherOptionsInfo.swift

@@ -249,8 +249,15 @@ public enum KingfisherOptionsInfoItem {
     ///
     case retryStrategy(RetryStrategy)
 
-
-    case lowDataSource(Source)
+    /// The `Source` should be loaded when user enables Low Data Mode and the original source fails with an
+    /// `NSURLErrorNetworkUnavailableReason.constrained` error. When this option is set, the
+    /// `allowsConstrainedNetworkAccess` property of the request for the original source will be set to `false` and the
+    /// `Source` in associated value will be used to retrieve the image for low data mode. Usually, you can provide a
+    /// low-resolution version of your image or a local image provider to display a placeholder.
+    ///
+    /// If not set or the `source` is `nil`, the device Low Data Mode will be ignored and the original source will
+    /// be loaded following the system default behavior, in a normal way.
+    case lowDataSource(Source?)
 }
 
 // Improve performance by parsing the input `KingfisherOptionsInfo` (self) first.

+ 32 - 0
Tests/KingfisherTests/ImageViewExtensionTests.swift

@@ -580,6 +580,14 @@ class ImageViewExtensionTests: XCTestCase {
         imageView.kf.setImage(with: url, options: [.onFailureImage(testImage)]) {
             result in
             XCTAssertNil(result.value)
+
+            if case KingfisherError.responseError(let reason) = result.error!,
+               case .URLSessionError(error: let nsError) = reason
+            {
+                XCTAssertEqual((nsError as NSError).code, 404)
+            } else {
+                XCTFail()
+            }
             XCTAssertEqual(self.imageView.image, testImage)
             exp.fulfill()
         }
@@ -841,6 +849,30 @@ class ImageViewExtensionTests: XCTestCase {
         waitForExpectations(timeout: 1, handler: nil)
     }
 
+    @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
+    func testLowDataModeSource() {
+        let exp = expectation(description: #function)
+
+        let url = testURLs[0]
+        stub(url, data: testImageData)
+
+        // Stub a failure of `.constrained`. It is what happens when an image downloading fails when low data mode on.
+        let brokenURL = testURLs[1]
+        let error = URLError(
+            .notConnectedToInternet,
+            userInfo: [NSURLErrorNetworkUnavailableReasonKey: URLError.NetworkUnavailableReason.constrained.rawValue]
+        )
+        stub(brokenURL, error: error)
+
+        imageView.kf.setImage(with: .network(brokenURL), options: [.lowDataSource(.network(url))]) { result in
+            XCTAssertNotNil(result.value)
+            XCTAssertEqual(result.value?.source.url, url)
+            XCTAssertEqual(result.value?.originalSource.url, brokenURL)
+            exp.fulfill()
+        }
+        waitForExpectations(timeout: 1, handler: nil)
+    }
+
 }
 
 extension KFCrossPlatformView: Placeholder {}

+ 4 - 0
Tests/KingfisherTests/Utils/StubHelpers.swift

@@ -42,5 +42,9 @@ func delayedStub(_ url: URL, data: Data, statusCode: Int = 200, length: Int? = n
 
 func stub(_ url: URL, errorCode: Int) {
     let error = NSError(domain: "stubError", code: errorCode, userInfo: nil)
+    stub(url, error: error)
+}
+
+func stub(_ url: URL, error: Error) {
     return stubRequest("GET", url.absoluteString as NSString).andFailWithError(error)
 }