Skip to content

SwiftUI Support

onevcat edited this page Dec 23, 2019 · 5 revisions

Kingfisher itself is a combination of image downloader, cache layer and some extensions of UI elements.

The image downloader and cache layer is platform independency, so you can easily reuse in a SwiftUI app. From version 5.8.0, we added a new wrapper framework, KingfisherSwiftUI, to provide a KFImage type to simplify the async image setting tasks. It conforms SwiftUI.View so you can integrate it to your SwiftUI app without effort. Behind the scene, it is driven by the powerful Kingfisher framework.

The same as SwiftUI, KingfisherSwiftUI is still in its early age. Please feel free to try and give any feedback!

Installation

In general, you can follow the steps in the Install Kingfisher guide. Choose the way you like, but with some small modification.

Swift Package Manager

Instead of adding Kingfisher to your project, you need to add KingfisherSwiftUI in the final step.

CocoaPods

SwiftUI support is provided in a sub-spec. So instead of specifying pod 'Kingfisher', you need pod 'Kingfisher/SwiftUI'.

Carthage

Both Kingfisher and KingfisherSwiftUI will be built when you run carthage update. You need to drag and add both frameworks to your project. Also remember to add both Kingfisher.framework and KingfisherSwiftUI.framework to the "Input Files" and "Output Files".

Using KFImage

Basic

KFImage wraps core features of Kingfisher to a Swift compatible View. Using KFImage is simple:

import SwiftUI

// If you are using SPM or Carthage, the SwiftUI support is defined in a new module.
import KingfisherSwiftUI
// If you are using CocoaPods, in which the SwiftUI support is defined in the same module.
import struct Kingfisher.KFImage

struct ContentView: View {
    let url = URL(
        string: "https://github.com/onevcat/Kingfisher/blob/master/images/kingfisher-1.jpg?raw=true"
    )
    var body: some View {
        KFImage(url)
    }
}

Kingfisher contains some general purpose types like Kingfisher.Image and Kingfisher.View. If you import the whole SwiftUI and Kingfisher at the same time, you will suffer from a name conflicting. To solve that, only import the necessary types from Kingfisher, such as import struct Kingfisher.KFImage or import class Kingfisher.KingfisherManager.

The code above will download the target url, and displays it in a SwiftUI.Image internally. At the same time, it stores the downloaded image in both memory cache and disk cache. When you set the same URL with KFImage, it will be loaded from the cache.

KFImage provides similar modifiers as SwiftUI.Image. Normally, you may want to specify a frame for the image:

KFImage(url)
    .resizable()
    .frame(width: 128, height: 128)

Or some modifiers from SwiftUI.View:

KFImage(url)
    .resizable()
    .frame(width: 128, height: 128)
    .cornerRadius(20)
    .shadow(radius: 5)

Configure KFImage

Besides of general view modifiers, KFImage also supports some others. It helps to give you a chance to react life cycles and do customization:

KFImage(url)
    .onSuccess { r in
        // r: RetrieveImageResult
        print("success: \(r)")
    }
    .onFailure { e in
        // e: KingfisherError
        print("failure: \(e)")
    }
    .placeholder {
        // Placeholder while downloading.
        Image(systemName: "arrow.2.circlepath.circle")
            .font(.largeTitle)
            .opacity(0.3)
    }

In List Cell

Loading an image in a list cell is a so common operation. It would be a waste if a cell is already out of screen, but the loading is not done yet. You can use .cancelOnDisappear to cancel any on-going download tasks automatically:

List {
    ForEach(0..<10) { i in
        KFImage(self.urls[i])
            .cancelOnDisappear(true)
}

Other Tips

Load from any Source

Besides of URL, KFImage accepts any original Source as its input. That means you can use customize cache key or load from an image data provider.

var resource: Resource {
    ImageResource(downloadURL: self.url!, cacheKey: "my_cache_key")
}

KFImage(source: .network(resource))

Options

Almost all options are still valid in KFImage, including the image processors and fade transition. Pass them as a parameter to the initializer:

KFImage(
    url,
    options: [
        .transition(.fade(0.2)),
        .processor(
            DownsamplingImageProcessor(size: CGSize(width: 50, height: 50))
        ),
        .cacheOriginalImage
    ])

Your knowledge of Kingfisher also applies in the KingfisherSwiftUI and KFImage type. So remember to read the Cheat Sheet of Kingfisher!

Clone this wiki locally