SDWebImageSwiftUI

repository·master·Indexed 25 days ago

https://github.com/sdwebimage/sdwebimageswiftui

A SwiftUI-native image loading framework built on top of SDWebImage. It provides high-performance async image loading, memory/disk caching, and support for animated formats like GIF and WebP. The library features WebImage for standard loading and AnimatedImage for advanced animation, vector support (SVG/PDF), and progressive rendering. It supports iOS 14+, macOS 11+, tvOS 14+, watchOS 7+, and visionOS 1+.

Tokens
4.8K
Snippets
15
Records
19
Agent score
32%

What's inside SDWebImageSwiftUI

  1. Choose between `WebImage` and `AnimatedImage`

    master

    The library provides two distinct views to balance SwiftUI compatibility with advanced feature requirements:

    FeatureWebImageAnimatedImage
    Primary Use CaseStandard static/simple animated imagesAdvanced animations, vectors, progressive loading
    SwiftUI IntegrationSeamless (uses Image internally)Uses UIViewRepresentable (may have minor layout edge cases)
    Animated SupportBasicAdvanced (Progressive, Vector, etc.)
    Layout ControlStandard SwiftUI modifiersRequires .resizable() and may need native view adjustments

    Recommendation: Start with WebImage. Switch to AnimatedImage only if you specifically need progressive rendering, vector formats, or advanced playback controls.

  2. Configure external loaders, caches, and coders

    master

    SDWebImageSwiftUI can be extended with external SDKs (like Firebase, WebP, AVIF, or Lottie) by configuring the shared managers in your App's initialization phase.

    Setup

    Register loaders, caches, or coders in your App.init() or AppDelegate:

    @main
    struct MyApp: App {
        init() {
            // Custom Firebase Storage Loader
            FirebaseApp.configure()
            SDImageLoadersManager.shared.loaders = [FirebaseUI.StorageImageLoader.shared]
            SDWebImageManager.defaultImageLoader = SDImageLoadersManager.shared
            
            // WebP/AVIF support
            SDImageCodersManager.shared.addCoder(SDImageWebPCoder.shared)
            SDImageCodersManager.shared.addCoder(SDImageAVIFCoder.shared)
        }
        // ...
    }

    Usage

    Some external loaders require specific URL representations:

    • FirebaseStorage: Use storageRef.sd_URLRepresentation.
    • PhotosKit: Use asset.sd_URLRepresentation.
    • Lottie: Use WebImage(url: lottieURL, isAnimating: $isAnimating).
    // Firebase Example
    let storageRef: StorageReference
    let storageURL = storageRef.sd_URLRepresentation
    
    // Lottie Example
    WebImage(url: lottieURL, isAnimating: $isAnimating)
  3. Use WebImage inside Button or NavigationLink

    master

    By default, SwiftUI's Button and NavigationLink apply an overlay (often a tint color) to their content. To prevent strange visual behavior when using WebImage or AnimatedImage inside these components, you must either override the .buttonStyle to PlainButtonStyle() or set the .renderingMode to .original.

    // Option 1: Use PlainButtonStyle
    Button(action: { /* Clicked */ }) {
        WebImage(url: url)
    }
    .buttonStyle(PlainButtonStyle())
    
    // Option 2: Use .original rendering mode
    NavigationView {
        NavigationLink(destination: Text("Detail view here")) {
            WebImage(url: url)
                .renderingMode(.original)
        }
    }
  4. Install SDWebImageSwiftUI via Swift Package Manager

    master

    You can integrate SDWebImageSwiftUI using Swift Package Manager (SPM).

    For App Integration

    Use Xcode 12 or higher to add the package dependency directly to your App target via the Xcode interface.

    For Downstream Frameworks

    If you are building a library/framework that depends on SDWebImageSwiftUI, add it to your Package.swift file:

    let package = Package(
        dependencies: [
            .package(url: "https://github.com/SDWebImage/SDWebImageSwiftUI.git", from: "3.0.0")
        ],
    )
  5. Configure SDWebImageSwiftUI for visionOS

    master

    As of v3.0.0, SDWebImageSwiftUI supports visionOS. However, CocoaPods and SPM are not yet supported for visionOS due to package manager limitations. You must use Xcode's built-in package manager to add the dependency as a local package.

    Manual Build Steps (Advanced)

    If you need to build the framework manually instead of using Xcode's package dependency:

    1. Clone SDWebImage, open SDWebImage.xcodeproj, and build the SDWebImage target for visionOS (set MACH_O_TYPE to static library if necessary).
    2. Clone SDWebImageSwiftUI, create the directory Carthage/Build/visionOS, and copy SDWebImage.framework into it.
    3. Open SDWebImageSwiftUI.xcodeproj and build the SDWebImageSwiftUI visionOS target.
  6. Configure SDWebImage features in `AppDelegate`

    master

    Since SDWebImageSwiftUI is built on top of SDWebImage, you can perform global configuration (like adding support for WebP, SVG, or AVIF, or setting up custom caches and loaders) in your app's AppDelegate or App struct.

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // 1. Add support for external formats
        SDImageCodersManager.shared.addCoder(SDImageWebPCoder.shared)
        SDImageCodersManager.shared.addCoder(SDImageSVGCoder.shared)
        
        // 2. Configure default HTTP headers
        SDWebImageDownloader.shared.setValue("image/webp,image/apng,image/*,*/*;q=0.8", forHTTPHeaderField: "Accept")
        
        // 3. Setup custom caches
        let cache = SDImageCache(namespace: "tiny")
        cache.config.maxMemoryCost = 100 * 1024 * 1024 // 100MB
        cache.config.maxDiskSize = 50 * 1024 * 1024   // 50MB
        SDImageCachesManager.shared.addCache(cache)
        SDWebImageManager.defaultImageCache = SDImageCachesManager.shared
        
        // 4. Setup loaders (e.g., Photos support)
        SDImageLoadersManager.shared.addLoader(SDImagePhotosLoader.shared)
        SDWebImageManager.defaultImageLoader = SDImageLoadersManager.shared
        
        return true
    }
  7. Render and tint vector images (SVG/PDF)

    master

    Both WebImage and AnimatedImage support vector images via SVG/PDF coders, but they behave differently:

    • AnimatedImage: Uses Apple's symbol image/vector drawing technology. It supports dynamic resizing without detail loss and uses UIKit/AppKit APIs. Use .tint() for coloring.
    • WebImage: Draws the vector image into a bitmap. It behaves like a standard PNG. Use .renderingMode(.template) combined with .foregroundColor() or .tint() to color it.

    To improve pixel density for bitmap rendering in either component, pass the .imageThumbnailPixelSize key in the context parameter.

    // WebImage with tinting
    WebImage(url: URL(string: "..."))
        .resizable()
        .renderingMode(.template)
        .foregroundColor(.red)
        .scaledToFit()
    
    // AnimatedImage with tinting and pixel size control
    AnimatedImage(url: URL(string: "..."), context: [.imageThumbnailPixelSize : CGSize(width: 100, height: 100)])
        .resizable()
        .renderingMode(.template)
        .tint(.red)
        .scaledToFit()
  8. Fix state loss in List, LazyStack, or LazyGrid

    master

    When using WebImage or AnimatedImage inside a List, LazyStack, or LazyGrid, SwiftUI may lose the view's state when the item scrolls out of the screen because these views are stateful. To ensure state remains in sync, do not place the WebImage directly inside the ForEach loop's top-level structure. Instead, wrap the image in a separate sub-view that holds its own @State.

    struct ContentView {
        struct BodyView {
            @State var url: String
            var body: some View {
                VStack {
                    WebImage(url)
                }
            }
        }
        @State var imageURLs: [String]
        var body: some View {
            List {
                ForEach(imageURLs, id: \.self) { url in
                    BodyView(url: url)
                }
            }
        }
    }
  9. Run Unit Tests for SDWebImageSwiftUI

    master

    The project includes unit tests to ensure code quality. Because SwiftUI is state-based, the project utilizes ViewInspector to inspect runtime attribute values (such as .frame or .image) for WebImage and AnimatedImage.

    Steps to run tests:

    1. Run pod install in the root directory to install necessary dependencies.
    2. Open SDWebImageSwiftUI.xcworkspace and wait for SwiftPM to finish downloading test dependencies.
    3. Select the SDWebImageSwiftUITests scheme and start the tests.
    pod install
  10. Run the SDWebImageSwiftUI Demo

    master

    To explore the library's capabilities, you can run the included demo application. The demo supports multiple Apple platforms including iOS, macOS, tvOS, watchOS, and visionOS.

    Steps to run:

    1. Open SDWebImageSwiftUI.xcworkspace.
    2. Wait for Swift Package Manager (SPM) to finish downloading dependencies.
    3. Select the SDWebImageSwiftUIDemo scheme (or the scheme for your target platform) and run the application.

    Demo Features:

    • Switching Image Types: Use the Switch action (right-click on macOS or tap on watchOS) to toggle between WebImage and AnimatedImage.
    • Clearing Cache: Use the Reload action (right-click on macOS or the button on watchOS) to clear the image cache.
    • Deleting URLs: On tvOS, use Swipe Left (via the menu button) to delete an image URL from the list.
    • Zooming: Use a pinch gesture (Digital Crown on watchOS or the play button on tvOS) to zoom in on the detail page image.
    • Progressive Loading: Clear the cache and navigate to a detail page to observe progressive loading in action.