URLImage Documentation

repository·main·Indexed 22 days ago

https://github.com/dmytro-anokhin/url-image

A SwiftUI-based library for downloading and caching remote images. It features a customizable view to handle empty, in-progress, failure, and success states, and supports both memory and disk caching via URLImageInMemoryStore and URLImageFileStore. The library includes tools for managing offline caching, controlling loading behavior with LoadOptions, and programmatic fetching using RemoteImagePublisher.

Tokens
2.3K
Snippets
10
Records
10
Agent score
28%

What's inside URLImage

  1. Install URLImage via Swift Package Manager

    main

    To use URLImage in your Xcode project, add it as a Swift Package dependency:

    1. In Xcode, open the File/Swift Packages/Add Package Dependency... menu.
    2. Paste the following package URL: https://github.com/dmytro-anokhin/url-image
    https://github.com/dmytro-anokhin/url-image
  2. Customize URLImage download states

    main

    URLImage manages four distinct download states, each of which can be customized using separate ViewBuilder closures:

    • Empty state: Displayed before the download starts or when there is nothing to show. Use the first closure.
    • In Progress state: Displayed during the download process. Use the inProgress: closure, which provides a progress value.
    • Failure state: Displayed if an error occurs. Use the failure: closure, which provides the error and a retry action.
    • Content state: Displayed when the image is successfully downloaded. Use the content: closure.
    URLImage(item.imageURL) {
        // Empty state
        EmptyView()
    } inProgress: { progress in
        // In Progress state
        Text("Loading...")
    } failure: { error, retry in
        // Failure state
        VStack {
            Text(error.localizedDescription)
            Button("Retry", action: retry)
        }
    } content: { image in
        // Content state
        image
            .resizable()
            .aspectRatio(contentMode: .fit)
    }
  3. Configure Offline Caching with URLImageStore

    main

    By default, URLImage uses the standard protocol cache policy (URLCache and Cache-Control headers), which requires an internet connection.

    To support offline use, you must configure a URLImageService with a fileStore (like URLImageFileStore) and inject it into the environment. When a file store is configured, URLImage follows the URLImageOptions.FetchPolicy instead of the protocol cache policy.

    ```swift
    import URLImage
    import URLImageStore
    
    @main
    struct MyApp: App {
        var body: some Scene {
            WindowGroup {
                FeedListView()
                    .environment(\.urlImageService, URLImageService(
                        fileStore: URLImageFileStore(),
                        inMemoryStore: URLImageInMemoryStore()
                    ))
            }
        }
    }

    Note: Ensure you include the URLImageStore library under "Frameworks, Libraries, and Embedded Content" in your target settings.

  4. Fix images displayed as single color rectangles in navigation or toolbars

    main

    Images in navigation bars or toolbars may appear as single-color rectangles because these areas use .renderingMode(.template) by default. To display the image with its original colors, specify .renderingMode(.original) within the URLImage content closure.

    URLImage(url) { image in
        image.renderingMode(.original)
    }
  5. Prevent image reloads during view updates

    main

    If URLImage is used alongside controls like TextField that trigger view updates, the image may reset to an empty state before the download completes. To prevent this, initialize a URLImageInMemoryStore at the application level and inject it into the environment via URLImageService.

    To clear the cache, use the following methods on your URLImageInMemoryStore instance:

    • removeImageWithURL
    • removeImageWithIdentifier
    • removeAllImages
    import SwiftUI
    import URLImage
    import URLImageStore
    
    @main
    struct MyApp: App {
        var body: some Scene {
            let urlImageService = URLImageService(fileStore: nil, inMemoryStore: URLImageInMemoryStore())
    
            return WindowGroup {
                ContentView()
                    .environment(\.urlImageService, urlImageService)
            }
        }
    }
  6. Basic Usage of URLImage

    main

    The simplest way to use URLImage is to provide a URL and a ViewBuilder closure to define how the downloaded image should be displayed. Note that the first argument must be a URL object; if you have a String, you must convert it to a URL first.

    import URLImage
    
    let url: URL = //...
    
    URLImage(url) { image in
        image
            .resizable()
            .aspectRatio(contentMode: .fit)
    }
  7. Download images without a view using RemoteImagePublisher

    main

    If you need to fetch an image programmatically (e.g., for background tasks or iOS 14 Widgets) without using a URLImage view, use RemoteImagePublisher via the URLImageService. This method respects caching and can be used with Combine.

    // Download a single image as a CGImage
    cancellable = URLImageService.shared.remoteImagePublisher(url)
        .tryMap { $0.cgImage }
        .catch { _ in Just(nil) }
        .sink { image in
            // image is CGImage or nil
        }
    
    // Download multiple images as an array of [CGImage?]
    let publishers = urls.map { URLImageService.shared.remoteImagePublisher($0) }
    
    cancellable = Publishers.MergeMany(publishers)
        .tryMap { $0.cgImage }
        .catch { _ in Just(nil) }
        .collect()
        .sink { images in
            // images is [CGImage?]
        }
  8. Control loading behavior with LoadOptions

    main

    By default, URLImage starts loading when the view renders. You can customize this using URLImageOptions.LoadOptions. Common options include:

    • .loadOnAppear: Starts loading when the view appears.
    • .cancelOnDisappear: Cancels the download when the view disappears.

    This is useful for optimizing performance in lists.

    List(/* ... */) {
        // ...
    }
    .environment(\.urlImageOptions, URLImageOptions(
        loadOptions: [.loadOnAppear, .cancelOnDisappear]
    ))
  9. Configure URLImageOptions via Environment

    main

    You can control download behavior (like maxPixelSize or loadOptions) using URLImageOptions. Instead of passing options to every view, you can inject them into the SwiftUI environment using the \.urlImageOptions key path. This allows you to set options for a specific view hierarchy.

    // Set options for a specific view
    URLImage(url) {
        image.resizable()
    }
    .environment(\.urlImageOptions, URLImageOptions(
        maxPixelSize: CGSize(width: 600.0, height: 600.0)
    ))
    
    // Or set options for the entire app hierarchy
    @main
    struct MyApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .environment(\.urlImageOptions, URLImageOptions(
                        maxPixelSize: CGSize(width: 600.0, height: 600.0)
                    ))
            }
        }
    }
  10. Access Image Information in content closure

    main

    The content closure of URLImage can provide both the Image and an ImageInfo object. ImageInfo allows you to access metadata such as the actual image size or the underlying CGImage object.

    URLImage(item.imageURL) { image, info in
        if info.size.width < 1024.0 {
            image
                .resizable()
                .aspectRatio(contentMode: .fit)
        } else {
            image
                .resizable()
                .aspectRatio(contentMode: .fill)
        }
    }