I would like to set UIImage to UIImageView directly, while preserving the ability to set the options.
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.
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:
imageView.kf.setImage(someURL) (assume image was downloaded before and it is in the cache, so no download task is being created here)imageView.kf.cancelDownloadTask() to prevent further downloading (and since there is no download task, I can't really cancel anything)imageView.setImage....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.
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:Then, set this provider when loading an image:
The image will be cached under the
imageNamekey and you can use all options in Kingfisher.