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.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Passing down the image size after successful load?

SirArkimedes opened this issue · comments

Is your feature request related to a problem? Please describe.
Not necessarily a problem, but was a use-case that came up with using the library!

On the application that I'm working with, we have a case where we want to know the size of the image and add different view modifiers to it depending upon a few conditions. Though, since the SwiftUI Image type doesn't have any size information we can't access it directly through the implementation.

Describe the solution you'd like
Maybe adding a size parameter to the Content callback when the image successfully loads? After adding this myself, it looks like it works as intended!

Here's my solution: SirArkimedes@3314f3b

Describe alternatives you've considered
Haven't considered much, but am thinking that it could be added somewhere else so it wouldn't need to be a breaking change to support the new parameter?

Additional context
I'd be willing to create a pull request with my change if it seems like an okay solution!

Here's a code sample of the Content block:

) { image, size in
      Group {
        if containerWidth > size.width {
          image
            .resizable()
            .fixedSize()
            .scaledToFit()
        } else {
          image
            .resizable()
            .scaledToFit()
        }
      }
    }

Hey,

thank you for the suggestion and most important for being ready to contribute back to the project.

From a general purpose perspective, it might be that other information about an image needed for a different case, or access to an image itself (CGImage object). Then adding more arguments to the closure won't be the best way.

And as you mention yourself, this will be a breaking change, so I prefer to keep a single argument as it is.

The solution, as I see it, is to provide access to the proxy object TransientImageType, in URLImage initializer. This will give an alternative of using a bit more complex API to get access to CGImage object.

public init(url: URL,
            options: URLImageOptions = URLImageService.shared.defaultOptions,
            empty: @escaping () -> Empty,
            inProgress: @escaping (_ progress: Float?) -> InProgress,
            failure: @escaping (_ error: Error, _ retry: @escaping () -> Void) -> Failure,
            content: @escaping (_ image: Image) -> Content)

public init(url: URL,
            options: URLImageOptions = URLImageService.shared.defaultOptions,
            empty: @escaping () -> Empty,
            inProgress: @escaping (_ progress: Float?) -> InProgress,
            failure: @escaping (_ error: Error, _ retry: @escaping () -> Void) -> Failure,
            content: @escaping (_ transientImage: TransientImageType) -> Content)

This will also require to add similar changes to URLImage extension to utilize default values for empty, inProgress, and failure state views.

I will try this change a bit later today, or more likely tomorrow, and see if it's convenient to use.

I added a new ImageInfo object to keep reference to CGImage object and related information. And also there are now two initializers:

init(url: URL, options: URLImageOptions, content: @escaping (_ image: Image) -> Content)
init(url: URL, options: URLImageOptions, content: @escaping (_ image: Image, _ info: ImageInfo) -> Content)

Unfortunately approach with adding TransientImageType initializer is not convenient, because it requires the client code to make the closure type explicit.

Also note that the size in ImageInfo is the real size. Meaning, if you use maxPixelSize to limit decoded image size (and it's limited by default) it's not affected by this setting.

The change is currently in master branch.

This is great! Thank you for adding this so quick!

This enhancement is now part of 2.2.0 release. I'm closing the issue. Feel free to reopen if you encounter any issues. Cheers.