Migration-To-8.md 5.1 KB

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:

// 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)
        }
    }
}
// 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:

// Old
extension YourType: AsyncImageDownloadRequestModifier {
    func modified(for request: URLRequest, reportModified: @escaping (URLRequest?) -> Void) {
        reportModified(request)
    }
}
// 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:

// 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)
        }
    }
}
// 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:

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.