Skip to content

Kingfisher 3.0 Migration Guide

onevcat edited this page Sep 21, 2016 · 7 revisions

Kingfisher 3.0 contains breaking changes since the world of Swift 3.0 is so different from Swift 2.x.

Once you decided to migrate your project to Swift 3, you have to also upgrade to Kingfisher 3, or you cannot keep using this framework in your project.

Basic

The most noticeable change is almost all APIs in Kingfisher now are following the Swift 3 API Design Guidelines. Although we want our users to keep using their code as much as possible, the gap between Swift 2 to Swift 3 is so huge which prevents us to do so. By upgrading to Kingfisher 3, you could use Kingfisher in a more Swifty way, but you have to spend some time to do the migration.

Depending on how did you use Kingfisher in your project, the migration progress may take several minutes to maybe half an hour. Things will be quite simple if you were just using the extension methods. Just change your original calling of image set method:

let URL = NSURL(string: "http://domain.com/image.png")!
imageView.kf_setImageWithURL(URL, 
                placeholderImage: nil,
                     optionsInfo: [.Transition(ImageTransition.Fade(1))],
                   progressBlock: nil,
               completionHandler: nil)

to follow the new API design in Swift 3:

let url = URL(string: "http://domain.com/image.png")!
imageView.kf.setImage(with: url, 
               placeholder: nil,
                   options: [.transition(.fade(1))],
             progressBlock: nil,
         completionHandler: nil)

If you are using other APIs from Kingfisher, you may want to check the API Diff part below, to modify your original code to follow new APIs.

API Diff

The full of API changes are listed below. Since Kingfisher is following Swift 3 API guidelines, you might be able to do the migration just following the guideline and ignore the diff documentation here. But we recommend to do a search and double check you are using the correct new APIs for your project.

General

Enum Member

All enum member now follow a camel naming with first letter lowercase. For example,

Before:

enum KingfisherOptionsInfoItem {
    case TargetCache(ImageCache)
    ...
}

Now changed to :

enum KingfisherOptionsInfoItem {
    case targetCache(ImageCache)
    ...
}

This affects all enum type in Kingfisher, including: KingfisherOptionsInfoItem, CacheType, KingfisherError and ImageTransition.


Types

Now all foundation types in Kingfisher are value-sematic version of these types. From Kingfisher 3, URL, Data or URLSession are used, instead of their class-varieties with NS prefix (NSURL, NSData or NSURLSession).


Resource

Before:

struct Resource { ... }

Now:

struct ImageResource { ... }

protocol Resource { .... }

A representation for resource could be downloaded/cached by Kingfisher, in which cacheKey and downloadURL are defined.


extension URL: Resource { ... }

URL now conforms to Resource, so you could use it directly in Kingfisher extension APIs.


Extensions

UIImageView / NSImageView Extensions

Before:

func kf_setImageWithResource(resource: Resource?,
                     placeholderImage: Image? = nil,
                          optionsInfo: KingfisherOptionsInfo? = nil,
                        progressBlock: DownloadProgressBlock? = nil,
                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now:

func kf.setImage(with resource: Resource?,
                   placeholder: Image? = nil,
                       options: KingfisherOptionsInfo? = nil,
                 progressBlock: DownloadProgressBlock? = nil,
             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

func kf_setImageWithURL(URL: NSURL?,
           placeholderImage: Image? = nil,
                optionsInfo: KingfisherOptionsInfo? = nil,
              progressBlock: DownloadProgressBlock? = nil,
          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now URL conforms to Resource protocol, so you could just use the Resource version above.


UIButton Extensions

Before:

func kf_setImageWithResource(resource: Resource?,
                       forState state: UIControlState,
                     placeholderImage: UIImage? = nil,
                          optionsInfo: KingfisherOptionsInfo? = nil,
                        progressBlock: DownloadProgressBlock? = nil,
                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now:

func kf.setImage(with resource: Resource?,
                     for state: UIControlState,
                   placeholder: UIImage? = nil,
                       options: KingfisherOptionsInfo? = nil,
                 progressBlock: DownloadProgressBlock? = nil,
             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Before:

func kf_setBackgroundImageWithResource(resource: Resource?,
                                 forState state: UIControlState,
                               placeholderImage: UIImage? = nil,
                                    optionsInfo: KingfisherOptionsInfo? = nil,
                                  progressBlock: DownloadProgressBlock? = nil,
                              completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now:

func kf.setBackgroundImage(with resource: Resource?,
                               for state: UIControlState,
                             placeholder: UIImage? = nil,
                                 options: KingfisherOptionsInfo? = nil,
                           progressBlock: DownloadProgressBlock? = nil,
                       completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

func kf_setImageWithURL(URL: NSURL?,
             forState state: UIControlState,
           placeholderImage: UIImage? = nil,
                optionsInfo: KingfisherOptionsInfo? = nil,
              progressBlock: DownloadProgressBlock? = nil,
          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Use the Resource version above.


func kf_setBackgroundImageWithURL(URL: NSURL?,
                       forState state: UIControlState,
                     placeholderImage: UIImage? = nil,
                          optionsInfo: KingfisherOptionsInfo? = nil,
                        progressBlock: DownloadProgressBlock? = nil,
                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Use the Resource version above.


var kf_showIndicatorWhenLoading: Bool { get set }

The indicators now could be customized. Use kf.indicatorType instead. If you just need a system activity indicator like before, set imageView.kf.indicatorType = .activity.


var kf.indicatorType { get set }

Use this property for setting & customizing the indicator while loading an image. See options below.


protocol Indicator { ... }

enum ImageView.IndicatorType {
    /// No indicator.
    case none
    /// Use system activity indicator.
    case activity
    /// Use an image as indicator. GIF is supported.
    case image(imageData: Data)
    /// Use a custom indicator, which conforms to the `Indicator` protocol.
    case custom(indicator: Indicator)
}

var kf.indicatorType: IndicatorType { get set }

NSButton Extensions

Before:

func kf_setImageWithResource(resource: Resource?,
                     placeholderImage: Image? = nil,
                          optionsInfo: KingfisherOptionsInfo? = nil,
                        progressBlock: DownloadProgressBlock? = nil,
                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now:

func kf.setImage(with resource: Resource?,
                   placeholder: Image? = nil,
                       options: KingfisherOptionsInfo? = nil,
                 progressBlock: DownloadProgressBlock? = nil,
             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Before:

func kf_setAlternateImageWithResource(resource: Resource?,
                              placeholderImage: Image? = nil,
                                   optionsInfo: KingfisherOptionsInfo? = nil,
                                 progressBlock: DownloadProgressBlock? = nil,
                             completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Now:

func kf.setAlternateImage(with resource: Resource?,
                            placeholder: Image? = nil,
                                options: KingfisherOptionsInfo? = nil,
                          progressBlock: DownloadProgressBlock? = nil,
                      completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

func kf_setImageWithURL(URL: NSURL?,
           placeholderImage: Image? = nil,
                optionsInfo: KingfisherOptionsInfo? = nil,
              progressBlock: DownloadProgressBlock? = nil,
          completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Use the Resource version above.


func kf_setAlternateImageWithURL(URL: NSURL?,
                    placeholderImage: Image? = nil,
                         optionsInfo: KingfisherOptionsInfo? = nil,
                       progressBlock: DownloadProgressBlock? = nil,
                   completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

Use the Resource version above.


Image Extensions

Before:

func kf_normalizedImage() -> Image

Now:

func kf.normalized -> Image

func kf.image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image

func kf.resize(to size: CGSize) -> Image

func kf.blurred(withRadius radius: CGFloat) -> Image

func kf.overlaying(with color: Color, fraction: CGFloat) -> Image

func kf.tinted(with color: Color) -> Image

func kf.adjusted(brightness: CGFloat, 
                   contrast: CGFloat, 
                 saturation: CGFloat, 
                    inputEV: CGFloat) -> Image

func kf.apply(_ filter: Filter) -> Image

KingfisherManager

Before:

class var sharedManager: KingfisherManager { get }

Now:

static let shared: KingfisherManager

init()

You should not create a KingfisherManager instance yourself. Use shared instead.


Before:

func retrieveImageWithResource(resource: Resource,
                            optionsInfo: KingfisherOptionsInfo?,
                          progressBlock: DownloadProgressBlock?,
                      completionHandler: CompletionHandler?) -> RetrieveImageTask

Now:

func retrieveImage(with resource: Resource,
                         options: KingfisherOptionsInfo?,
                   progressBlock: DownloadProgressBlock?,
               completionHandler: CompletionHandler?) -> RetrieveImageTask

func retrieveImageWithURL(URL: NSURL,
                  optionsInfo: KingfisherOptionsInfo?,
                progressBlock: DownloadProgressBlock?,
            completionHandler: CompletionHandler?) -> RetrieveImageTask

Use the Resource version above.


ImageCache

Before:

let KingfisherDidCleanDiskCacheNotification: String

Now:

public extension Notification.Name {
    static var KingfisherDidCleanDiskCache: Notification.Name { get }
}

Before:

class var defaultCache: ImageCache { get }

Now:

static let `default`: ImageCache

Before:

func storeImage(image: Image, 
                originalData: NSData? = nil, 
                forKey key: String, 
                toDisk: Bool = true, 
                completionHandler: (() -> Void)? = nil)

Now:

func store(_ image: Image,
           original: Data? = nil,
           forKey key: String,
           processorIdentifier identifier: String = "",
           cacheSerializer serializer: CacheSerializer = DefaultCacheSerializer.default,
           toDisk: Bool = true,
           completionHandler: (() -> Void)? = nil)

Leave identifier and serializer their default values while upgrading. They are used with ImageProcessor and CacheSerializer to customize the image decoding and serialization.


Before:

func removeImageForKey(key: String, 
                       fromDisk: Bool = true, 
                       completionHandler: (() -> Void)? = nil)

Now:

func removeImage(forKey key: String,
                 processorIdentifier identifier: String = "",
                 fromDisk: Bool = true,
                 completionHandler: (() -> Void)? = nil)

Leave identifier its default values while upgrading. It is used with ImageProcessor to customize the image decoding.


Before:

func retrieveImageForKey(key: String, 
                     options: KingfisherOptionsInfo?, 
           completionHandler: ((Image?, CacheType) -> ())?) -> RetrieveImageDiskTask?

Now:

func retrieveImage(forKey key: String,
                      options: KingfisherOptionsInfo?,
            completionHandler: ((Image?, CacheType) -> ())?) -> RetrieveImageDiskTask?

Before:

func retrieveImageInMemoryCacheForKey(key: String) -> Image?

Now:

func retrieveImageInMemoryCache(forKey key: String, 
                                   options: KingfisherOptionsInfo? = nil) -> Image?

Before:

func retrieveImageInDiskCacheForKey(key: String, 
                                  scale: CGFloat = 1.0, 
                      preloadAllGIFData: Bool = false) -> Image?

Now:

func retrieveImageInDiskCache(forKey key: String, 
                                 options: KingfisherOptionsInfo? = nil) -> Image?

Wrap the scale and preloadAllGIFData into KingfisherOptionsInfo if you were using them.


Before:

func clearDiskCacheWithCompletionHandler(completionHander: (()->())?)

Now:

func clearDiskCache(completion handler: (()->())? = nil)

Before:

func cleanExpiredDiskCacheWithCompletionHander(completionHandler: (()->())?)

Now:

func cleanExpiredDiskCache(completion handler: (()->())? = nil)

func cachedImageExistsforURL(url: NSURL) -> Bool

Use result of isImageCached(forKey:processorIdentifier:) instead.


Before:

func isImageCachedForKey(key: String) -> CacheCheckResult

Now:

func isImageCached(forKey key: String, 
                   processorIdentifier identifier: String = "") -> CacheCheckResult

Before:

func hashForKey(key: String) -> String

Now:

func hash(forKey key: String, 
          processorIdentifier identifier: String = "") -> String

Before:

func calculateDiskCacheSizeWithCompletionHandler(completionHandler: ((size: UInt) -> ()))

Now:

func calculateDiskCacheSize(completion handler: ((_ size: UInt) -> ()))

Before:

func cachePathForKey(key: String) -> String

Now:

func cachePath(forKey key: String, 
               processorIdentifier identifier: String = "") -> String

ImageDownloader

var requestModifier: ((inout URLRequest) -> Void)?

Use .requestModifier in KingfisherOptionsInfo instead. See Modify a request before sending for more.


Before:

class var defaultDownloader: ImageDownloader { get }

Now:

static let `default`: ImageDownloader

Before:

func downloadImageWithURL(URL: NSURL,
                      options: KingfisherOptionsInfo?,
                progressBlock: ImageDownloaderProgressBlock?,
            completionHandler: ImageDownloaderCompletionHandler?) -> RetrieveImageDownloadTask?

Now:

func downloadImage(with url: URL,
                    options: KingfisherOptionsInfo? = nil,
              progressBlock: ImageDownloaderProgressBlock? = nil,
          completionHandler: ImageDownloaderCompletionHandler? = nil) -> RetrieveImageDownloadTask?

RetrieveImageDownloadTask

Before:

var URL: NSURL? { get }

Now:

var url: URL? { get }

ImageDownloaderDelegate

Before:

func imageDownloader(downloader: ImageDownloader, 
         didDownloadImage image: Image, 
                     forURL URL: NSURL, 
          withResponse response: NSURLResponse)

Now:

imageDownloader(_ downloader: ImageDownloader, 
           didDownload image: Image, 
                     for url: URL, 
               with response: URLResponse?)

func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool

Use this delegate method to specify valid HTTP status code for a request.


AuthenticationChallengeResponable

Before:

func downloader(downloader: ImageDownloader, 
                didReceiveChallenge challenge: NSURLAuthenticationChallenge, 
                completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)

Now:

func downloader(_ downloader: ImageDownloader, 
                didReceive challenge: URLAuthenticationChallenge, 
                completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)

ImagePrefetcher

Before:

init(urls: [NSURL], 
     optionsInfo: KingfisherOptionsInfo? = nil,
     progressBlock: PrefetcherProgressBlock? = nil,
     completionHandler: PrefetcherCompletionHandler? = nil)

Now:

init(urls: [URL], 
     options: KingfisherOptionsInfo? = nil,
     progressBlock: PrefetcherProgressBlock? = nil,
     completionHandler: PrefetcherCompletionHandler? = nil)

The URL version of init method is kept since there is no covariance in Swift protocol.


Before:

init(resources: [Resource], 
     optionsInfo: KingfisherOptionsInfo? = nil,
     progressBlock: PrefetcherProgressBlock? = nil,
     completionHandler: PrefetcherCompletionHandler? = nil)

Now:

init(resources: [Resource],
     options: KingfisherOptionsInfo? = nil,
     progressBlock: PrefetcherProgressBlock? = nil,
     completionHandler: PrefetcherCompletionHandler? = nil)

ImageTransition

Enum members now follow lowercase naming convention. See "Enum Member" part of this documentation.


KingfisherOptionsInfo

Enum members now follow lowercase naming convention. See "Enum Member" part of this documentation.


Before:

case TargetCache(ImageCache?)

Now:

case targetCache(ImageCache)

Only accept non-optional value now. Use ImageCache.default if you were passing a nil before.


Before:

case Downloader(ImageDownloader?)

Now:

case downloader(ImageDownloader)

Only accept non-optional value now. Use ImageDownloader.default if you were passing a nil before.


case requestModifier(ImageDownloadRequestModifier)

Use this option to pass a request modifier instead of setting the requestModifier property in ImageDownloader.


case processor(ImageProcessor)

case cacheSerializer(CacheSerializer)

ImageProcessor

public enum ImageProcessItem { ... }

protocol ImageProcessor { ... }

See Processor part in Cheat Sheet to know more about the processor.


struct DefaultImageProcessor: ImageProcessor { ... }
struct RoundCornerImageProcessor: ImageProcessor { ... }
struct ResizingImageProcessor: ImageProcessor { ... }
struct BlurImageProcessor: ImageProcessor { ... }
struct OverlayImageProcessor: ImageProcessor { ... } 
struct TintImageProcessor: ImageProcessor { ... }
struct ColorControlsProcessor: ImageProcessor { ... } 
struct BlackWhiteProcessor: ImageProcessor { ... }

These are built-in processor of Kingfisher. You could easily create your own processor to decode/filter any data/image to final image. See Create and use your own processor for more.


CacheSerializer

protocol CacheSerializer { ... }

See Serializer part in Cheat Sheet to know more about the cache serializer.


struct DefaultCacheSerializer: CacheSerializer { ... }

Default serializer to serialize/deserialize basic image format: PNG, JEPG and GIF. See Create and use your own serializer to know how to create and use a serializer yourself.

ImageDownloadRequestModifier

protocol ImageDownloadRequestModifier { ... }

add

struct AnyModifier: ImageDownloadRequestModifier { ... }

A block-based modifier which supply an easy way to implement a modifier. See Modify a request before sending.