-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
171 additions
and
0 deletions.
There are no files selected for viewing
171 changes: 171 additions & 0 deletions
171
Sources/Documentation.docc/MigrationGuide/Migration-To-8.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |