dmytro-anokhin / url-image

AsyncImage before iOS 15. Lightweight, pure SwiftUI Image view, that displays an image downloaded from URL, with auxiliary views and local cache.
MIT License
1.11k stars 97 forks source link

Provide / document an API to download images, outside of a SwiftUI context #70

Open alexd6631 opened 4 years ago

alexd6631 commented 4 years ago

I am using URL Image in a Swift UI project, and I would like to reuse the downloading/caching logic of URL Image, but outside a SwiftUI hierarchy.

My specific use case is to create an attachment for a local notification, and it only accepts on-disk file URLs. Since these images are profile pictures and likely to be already in URLImage cache, it makes sense to reuse the cache.

Digging inside the code source, it appears it should be possible by using directly DownloadService, but : 1/ It is not clear if this API is public, or used internally for separting concerns and may be subject to evolution 2/ The API feel a bit low level, for instance it is not clear what fileIdentifier should be by default, or why a separated addHandler/load is necessary, so it maybe interesting to put a facade in URLImageService to make simple calls like :

URLImageService.load(url) { image, err in ... }

A way to get the local file path/URL, maybe as an additional parameter of the above closure, would be very helpful in my case.

Leinadzet commented 4 years ago

This! +1

Vercisor commented 4 years ago

This would be awesome!

dmytro-anokhin commented 4 years ago

Hey, this is not trivial because data logic is tightly coupled with image decoding. But I'm working on next version of the package and it will allow download/use cached images without view part. I hope to share updates soon.

Leinadzet commented 4 years ago

Thx for the hard work!

dmytro-anokhin commented 4 years ago

Version 2.0 uses new structure that allows me to implement this feature. I will keep this issue updated.

godefroydlb commented 3 years ago

You all work is really nice. I am stuck trying to implement image download outside a view using "URLImageService.shared.makeRemoteImage". It would be very nice to have some working example of this use case

dmytro-anokhin commented 3 years ago

Hey, sure, you can write a helper function like this: https://gist.github.com/dmytro-anokhin/51aaeecb03a4e8249d7783cc5c60cb3b

godefroydlb commented 3 years ago

Hi Dmytro

And thank you. It is a really nice work you are doing because this feature to manage easily external image is really useful.

I was not able to compile your example because I am not fluent in Result type management. I am not a professional developer.

I have URL Image package in version 2.2.0 and I am getting these errors. It might be because you have a component, that I do not have.

Error messages are : Result<ImageInfo, Error> -> Cannot specialize non-generic type 'Result' completion(.success(transientImage.info))-> Type Result has no member success completion(.failure(error)) -> Type Result has no member failure

If you have time to have a look, would be much appreciated.

Le 8 janv. 2021 à 21:37, Dmytro Anokhin notifications@github.com a écrit :

Hey, sure, you can write a helper function like this: https://gist.github.com/dmytro-anokhin/51aaeecb03a4e8249d7783cc5c60cb3b https://gist.github.com/dmytro-anokhin/51aaeecb03a4e8249d7783cc5c60cb3b — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dmytro-anokhin/url-image/issues/70#issuecomment-757111257, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADY54INSOF265XKROSSUE6LSZABSZANCNFSM4M67YR4A.

dmytro-anokhin commented 3 years ago

Replied in the gist, not to create noise here.

dmytro-anokhin commented 3 years ago

Hey there, I added RemoteImagePublisher in 2.2.1 that allows to use Combine for downloading or retrieving images. The output is ImageInfo object. You can use it to get CGImage like this:

cancellable = URLImageService.shared.remoteImagePublisher(url)
            .tryMap { $0.cgImage }
            .sink(receiveCompletion: { _ in }, receiveValue: { image in
                print(image)
            })

Documentation coming soon. Cheers.

dmytro-anokhin commented 3 years ago

Hey,

I know this issue is long overdue, but I was struggling to come up with a nice API that won't overcomplicate the package. Finally, I think I got there 🙂

In 2.2.1 there is a new publisher added to the package: RemoteImagePublisher. It encapsulates all necessary operations to fetch an image. Because under the hood it uses the same objects as URLImage view it will behave in the same manner, use the same cache, and return cached image if available.

Here is documentation, and some examples how to use it: https://github.com/dmytro-anokhin/url-image#fetching-an-image

Please let me know if there is something else that I miss/you expect. Otherwise I will close this issue soon.

Cheers.

filipkrayem commented 3 years ago

Hi @dmytro-anokhin, the documentation seems to be outdated and the code samples do not work. Could you please update the documentation and the example?

For example, URLImageService does not have a shared property, and the exposed RemoteImagePublisher is the struct that accepts self as an argument, as opposed to the expected function. Is the RemoteImagePublisher struct even supposed to be public?

I've been able to access the remoteImagePublisher function through @Environment(\.urlImageService) var service: URLImageService, but that's not clearly specified and the code snippet implies you're supposed to use URLImageService and not the environment value.

Also, I think it's worth mentioning that the Just struct needs to be imported from Combine.

The code also never seems to get to the sink stage. I'm pretty new to Swift and never dealt with concurrency, so maybe I'm doing something wrong?

let cancellable = service.remoteImagePublisher(photoUrls.full, identifier: "image")
            .tryMap { $0.cgImage }
            .catch { _ in
                Just(nil)
            }
            .sink { image in
                print("sink") // never prints
                myCGImage = image
            }

Hope you're doing well. Thanks

dmytro-anokhin commented 3 years ago

Hey @FilipK999, thanks for bringing up. shared service is indeed gone (maybe I should resurrect it 🤔). This is because it is up to the app to setup the service that fits the purpose. While I'm updating the documentations, you can use ImageDownloader sample code here: https://github.com/dmytro-anokhin/url-image-demo. Hope this helps.