Kingfisher: Set UIImage to UIImageView directly, while preserving the options

Created on 21 Apr 2017  Â·  6Comments  Â·  Source: onevcat/Kingfisher

Check List

Issue Description

I would like to set UIImage to UIImageView directly, while preserving the ability to set the options.

What

What I'm looking for is a version of the following function

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

in the following manner

func setImage(with image: Image?,
              options: KingfisherOptionsInfo? = nil) -> Void

This way, we get to keep the functionality of options like .transition and .processor when setting instances of UIImage directly.

Most helpful comment

@artem-alexandrov @smaljaar Thanks for commenting on it again.

Now, Kingfisher supports any data provider, so I think it is easy to implement now. First, create a provider based on the UIImage:

struct UIImageProvider: ImageDataProvider {

    let cacheKey: String
    let imageData: Data?

    init(image: UIImage, name: String) {
        cacheKey = name
        imageData = image.pngData()
    }

    func data(handler: @escaping (Result<Data, Error>) -> Void) {
        if let data = imageData {
            handler(.success(data))
        } else {
            handler(.failure(cannotConverToDataError))
        }
    }
}

Then, set this provider when loading an image:

let name = "imageName"
let imageProvider = UIImageProvider(image: UIImage(named: name)!, name: name)
imageView.kf.setImage(with: .provider(imageProvider))

The image will be cached under the imageName key and you can use all options in Kingfisher.

All 6 comments

If your images are already in the app bundle or disk, you could just pass the local url of that image to Kingfisher to do so, like this:

let url = Bundle.main.url(forResource: "my-image", withExtension: "png", subdirectory: nil)!
imageView.kf.setImage(with: url, options: someOptions)

It is now not supported to set the images directly in the behavior you need now. Some options like . processor or cacheSerializer are only work with ImageDownloader or ImageCache, and they are not actually related to the image view.

For processors, all the built-in processors are marked as public, so you could just create a processor and apply it to your image object directly, then set it to an image view.

The transition will not be hard either, it is nothing more than an invoking to UIView.transition(with:duration:animations:).

Generally, it will not be difficult to implement it in the base of current Kingfisher. However, I think it is not a good idea to supply such a method in this framework. What Kingfisher does want to handle is networking images and we need to be focus on this as much as possible.

Thank you for proposing it , and let me know what you think about it.

Thank you for a quick response. I agree with you on the scope side of things, just wanted to hear your thoughts on this.

For now, I'm accomplishing my needs with processor.process(item: .image(image), options: options) and setting the resulting image to the UIImageView, together with other manual effects like fade, as you suggested.

@damirstuhec

Thank you for your understanding on this!

If anyone needs this feature later, please feel free to add a comment. We will keep an eye to see whether it would be a widely wanted feature.

Hi! Looks like I need something like what is requested in this issue. The issue I have is that I need to set either a local UIImage or a remote resource sometimes (based on some logic), and local images are in XCAssets folder, meaning I can't get URL to it.

If I set it directly in a manner like:

  1. imageView.kf.setImage(someURL) (assume image was downloaded before and it is in the cache, so no download task is being created here)
  2. then I understand that I need to set local UIImage from XCAsset into the same UIImageView, so I call imageView.kf.cancelDownloadTask() to prevent further downloading (and since there is no download task, I can't really cancel anything)
  3. And once I "cancelled" downloading, I'm setting UIImage directly, like imageView.setImage....
  4. After that is done, getting image from the cache started in step 1 is finished and the image is being reset, ending up with wrong image in my view
    (it's actual for UITableView/Cell reloading)

So I'm currently trying to extend Kingfisher to allow me setting local UIImage with kf.setImage (also applying processing -> caching of processed image) and it doesn't seems to be an easy work :)
Can you help me with it?

I also was looking around for a way to set an image directly. My use case: the user selects an image, then I start uploading the image. After the user selected the image, I immediately want to set the image by UIImage, only in case the upload fails, then there will be an error message and the old image will be set back. I understand Kingfisher is focussed on networking, still I think it be nice/intuitive if there was a setImage method available that took a UIImage.

@artem-alexandrov @smaljaar Thanks for commenting on it again.

Now, Kingfisher supports any data provider, so I think it is easy to implement now. First, create a provider based on the UIImage:

struct UIImageProvider: ImageDataProvider {

    let cacheKey: String
    let imageData: Data?

    init(image: UIImage, name: String) {
        cacheKey = name
        imageData = image.pngData()
    }

    func data(handler: @escaping (Result<Data, Error>) -> Void) {
        if let data = imageData {
            handler(.success(data))
        } else {
            handler(.failure(cannotConverToDataError))
        }
    }
}

Then, set this provider when loading an image:

let name = "imageName"
let imageProvider = UIImageProvider(image: UIImage(named: name)!, name: name)
imageView.kf.setImage(with: .provider(imageProvider))

The image will be cached under the imageName key and you can use all options in Kingfisher.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sindresorhus picture sindresorhus  Â·  3Comments

SURYAKANTSHARMA picture SURYAKANTSHARMA  Â·  4Comments

kbpontius picture kbpontius  Â·  3Comments

indrajitsinh picture indrajitsinh  Â·  5Comments

Tarpsvo picture Tarpsvo  Â·  5Comments