|
@@ -0,0 +1,171 @@
|
|
|
|
|
+# Migrating from v7 to v8
|
|
|
|
|
+
|
|
|
|
|
+This guide assists you in updating Kingfisher from version 7 to version 8.
|
|
|
|
|
+
|
|
|
|
|
+## Overview
|
|
|
|
|
+
|
|
|
|
|
+Kingfisher 8.0 introduces breaking changes from its predecessor. This document highlights the major updates and significant API modifications.
|
|
|
|
|
+
|
|
|
|
|
+## Deployment Target
|
|
|
|
|
+
|
|
|
|
|
+Starting with Kingfisher 8.0, the minimum supported versions are:
|
|
|
|
|
+
|
|
|
|
|
+- iOS 13.0
|
|
|
|
|
+- macOS 10.15
|
|
|
|
|
+- tvOS 13.0
|
|
|
|
|
+- watchOS 6.0
|
|
|
|
|
+- visionOS 1.0
|
|
|
|
|
+
|
|
|
|
|
+## Migration Steps and Insights
|
|
|
|
|
+
|
|
|
|
|
+First, ensure there are no existing warnings from Kingfisher. Several deprecated methods and properties have been removed in version 8.
|
|
|
|
|
+
|
|
|
|
|
+For the breaking changes, review the sections below for any utilized features and symbols.
|
|
|
|
|
+
|
|
|
|
|
+### Disk Cache Changes
|
|
|
|
|
+
|
|
|
|
|
+Version 8 updates the disk cache hash calculation method, invalidating existing caches. Kingfisher's disk cache is resilient, automatically re-downloading and caching data if missing. Typically, no action is required unless your application's logic heavily relies on disk cache, which is generally not recommended.
|
|
|
|
|
+
|
|
|
|
|
+### Swift Concurrency APIs
|
|
|
|
|
+
|
|
|
|
|
+Kingfisher now embraces Swift's `async` keyword, enhancing most asynchronous APIs previously implemented with completion handlers. While the traditional APIs remain in struct and class types, some protocol methods have transitioned to `async` without the traditional ones.
|
|
|
|
|
+
|
|
|
|
|
+Ensure your implementations conform to these changes.
|
|
|
|
|
+
|
|
|
|
|
+#### `ImageDownloadRedirectHandler` Protocol
|
|
|
|
|
+
|
|
|
|
|
+The `handleHTTPRedirection(for:response:newRequest:completionHandler:)` method has been replaced with an asynchronous counterpart. Update your implementation accordingly:
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// Old
|
|
|
|
|
+extension YourType: ImageDownloadRedirectHandler {
|
|
|
|
|
+ func handleHTTPRedirection(
|
|
|
|
|
+ for task: Kingfisher.SessionDataTask,
|
|
|
|
|
+ response: HTTPURLResponse,
|
|
|
|
|
+ newRequest: URLRequest,
|
|
|
|
|
+ completionHandler: @escaping (URLRequest?) -> Void
|
|
|
|
|
+ ) {
|
|
|
|
|
+ // Do something with the result, potentially in async way
|
|
|
|
|
+ requestUpdater.update(newRequest) { result in
|
|
|
|
|
+ completionHandler(result)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// New
|
|
|
|
|
+extension YourType: ImageDownloadRedirectHandler {
|
|
|
|
|
+ func handleHTTPRedirection(
|
|
|
|
|
+ for task: Kingfisher.SessionDataTask,
|
|
|
|
|
+ response: HTTPURLResponse,
|
|
|
|
|
+ newRequest: URLRequest
|
|
|
|
|
+ ) async -> URLRequest? {
|
|
|
|
|
+ let result = await requestUpdater.update(newRequest)
|
|
|
|
|
+ return result
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### `AsyncImageDownloadRequestModifier` Protocol
|
|
|
|
|
+
|
|
|
|
|
+The `modified(for:reportModified:)` method is now asynchronous. Reimplement it if used:
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// Old
|
|
|
|
|
+extension YourType: AsyncImageDownloadRequestModifier {
|
|
|
|
|
+ func modified(for request: URLRequest, reportModified: @escaping (URLRequest?) -> Void) {
|
|
|
|
|
+ reportModified(request)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// New
|
|
|
|
|
+extension YourType: AsyncImageDownloadRequestModifier {
|
|
|
|
|
+ func modified(for request: URLRequest) async -> URLRequest? {
|
|
|
|
|
+ return request
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### `AuthenticationChallengeResponsible` Protocol
|
|
|
|
|
+
|
|
|
|
|
+The following methods have been updated to async versions:
|
|
|
|
|
+
|
|
|
|
|
+- `downloader(_:didReceive:completionHandler:)`
|
|
|
|
|
+- `downloader(_:task:didReceive:completionHandler:)`
|
|
|
|
|
+
|
|
|
|
|
+Ensure your implementation is current:
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// Old
|
|
|
|
|
+extension YourType: AuthenticationChallengeResponsible {
|
|
|
|
|
+ func downloader(
|
|
|
|
|
+ _ downloader: ImageDownloader,
|
|
|
|
|
+ didReceive challenge: URLAuthenticationChallenge,
|
|
|
|
|
+ completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
|
|
|
|
|
+ )
|
|
|
|
|
+ {
|
|
|
|
|
+ generateCredential { credential in
|
|
|
|
|
+ completionHandler(.useCredential, credential)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ func downloader(
|
|
|
|
|
+ _ downloader: ImageDownloader,
|
|
|
|
|
+ task: URLSessionTask,
|
|
|
|
|
+ didReceive challenge: URLAuthenticationChallenge,
|
|
|
|
|
+ completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
|
|
|
|
|
+ )
|
|
|
|
|
+ {
|
|
|
|
|
+ generateCredential { credential in
|
|
|
|
|
+ completionHandler(.useCredential, credential)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+// New
|
|
|
|
|
+extension YourType: AuthenticationChallengeResponsible {
|
|
|
|
|
+ func downloader(
|
|
|
|
|
+ _ downloader: ImageDownloader,
|
|
|
|
|
+ didReceive challenge: URLAuthenticationChallenge
|
|
|
|
|
+ ) async -> (URLSession.AuthChallengeDisposition, URLCredential?)
|
|
|
|
|
+ {
|
|
|
|
|
+ let credential = await generateCredential()
|
|
|
|
|
+ return (.useCredential, credential)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ func downloader(
|
|
|
|
|
+ _ downloader: ImageDownloader,
|
|
|
|
|
+ task: URLSessionTask,
|
|
|
|
|
+ didReceive challenge: URLAuthenticationChallenge
|
|
|
|
|
+ ) async -> (URLSession.AuthChallengeDisposition, URLCredential?)
|
|
|
|
|
+ {
|
|
|
|
|
+ let credential = await generateCredential()
|
|
|
|
|
+ return (.useCredential, credential)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Type Adjustments
|
|
|
|
|
+
|
|
|
|
|
+#### `ColorElement`
|
|
|
|
|
+
|
|
|
|
|
+`Filter.ColorElement` has evolved from a typealias for a tuple to a `struct`. Instantiate `ColorElement` using its initializer:
|
|
|
|
|
+
|
|
|
|
|
+```swift
|
|
|
|
|
+let brightness, contrast, saturation, inputEV: CGFloat
|
|
|
|
|
+
|
|
|
|
|
+// Old
|
|
|
|
|
+let colorElement: Filter.ColorElement = (brightness, contrast, saturation, inputEV)
|
|
|
|
|
+
|
|
|
|
|
+// New
|
|
|
|
|
+let colorElement = Filter.ColorElement(brightness, contrast, saturation, inputEV)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### `DownloadTask`
|
|
|
|
|
+
|
|
|
|
|
+`DownloadTask` has been redefined as a `class` instead of a `struct`, without further API modifications.
|