CommonTasks_Serializer.md 3.8 KB

Common Tasks - Serializer

CacheSerializer is utilized to convert data into an image object for retrieval from disk cache, and conversely, for storing images to the disk cache.

Use the default serializer

// Just without anything
imageView.kf.setImage(with: url)
// It equals to
imageView.kf.setImage(with: url, options: [.cacheSerializer(DefaultCacheSerializer.default)])

DefaultCacheSerializer is responsible for converting cached data into a corresponding image object and vice versa. It supports PNG, JPEG, and GIF formats by default.

When storing an image to disk, if the original data is available (for example, when the image is just downloaded), DefaultCacheSerializer uses it to determine the format. If original is nil (for example, when the image is retrieved from cache), Kingfisher will try to infer the format: if the image still carries embedded GIF data, it will be stored as GIF; otherwise it falls back to encoding as PNG.

Notes for animated images and custom processors

For animated images, Kingfisher keeps the original GIF bytes as an internal associated object on the image instance. If a custom ImageProcessor creates and returns a new UIImage/NSImage instance from an animated image, this internal animated data is not automatically carried over, and the disk cache may fall back to encoding as PNG (first frame only).

To avoid this:

  • For animated inputs, return the input image directly when possible.
  • If you need to create a new image instance in the .image branch, copy Kingfisher internal states to the new image by calling KingfisherWrapper/copyKingfisherState(to:).
  • If your goal is to avoid re-encoding, consider caching original data by using a serializer with CacheSerializer/originalDataUsed enabled (e.g. configure DefaultCacheSerializer/preferCacheOriginalData).

Enforce a format

To enforce a specific image format, use FormatIndicatedCacheSerializer, which offers serializers for all supported formats: FormatIndicatedCacheSerializer/png, FormatIndicatedCacheSerializer/jpeg, and FormatIndicatedCacheSerializer/gif.

Use PNG serializer when rounding image corner

While DefaultCacheSerializer aims to preserve the original format of input image data, there are scenarios where this behavior might not meet your needs. For example, when using a RoundCornerImageProcessor, it's often desirable to maintain an alpha channel for transparency around the corners. JPEG images, lacking an alpha channel, would not support this transparency when saved. To ensure the presence of an alpha channel by converting images to PNG, you can set the PNG serializer explicitly:

let roundCorner = RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, 
    options: [.processor(roundCorner), 
              .cacheSerializer(FormatIndicatedCacheSerializer.png)]
)

Creating customized serializer

Make a type conforming to CacheSerializer by implementing data(with:original:) and image(with:options:): To create a type that conforms to CacheSerializer, implement the CacheSerializer/data(with:original:) and CacheSerializer/image(with:options:):

struct MyCacheSerializer: CacheSerializer {
    func data(with image: Image, original: Data?) -> Data? {
        return MyFramework.data(of: image)
    }
    
    func image(with data: Data, options: KingfisherParsedOptionsInfo?) -> Image? {
        return MyFramework.createImage(from: data)
    }
}

Then pass it to the KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-9h820 methods:

let serializer = MyCacheSerializer()
let url = URL(string: "https://yourdomain.com/example.png")
imageView.kf.setImage(with: url, options: [.cacheSerializer(serializer)])