SDWebImageSwiftUI: Memory issue when caching too many GIFs in List / LazyVStack

Clearing memory caches manually doesn’t help. Reproduced in 2.0.0 & 2.0.1.

I used 70 gifs (5-7 MB each) to reproduce with my 4GB memory iPhone.

import SwiftUI
import SDWebImageSwiftUI

struct ContentView: View {
    let gifs = // bunch of gifs here
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(gifs, id: \.hashValue) { gif in
                    WebImage(url: URL(string: gif))
                        .resizable()
                        .indicator(.progress)
                        .scaledToFit()
                }
            }
        }
    }
}

About this issue

Most upvoted comments

@tatsuz0u Thank you for the example code, I’m able to reproduce with LazyVStack. A little bit hacky but can we do something similar to this:

public struct LazyReleaseableWebImage<T: View>: View {

    @State
    private var shouldShowImage: Bool = false

    private let content: () -> WebImage
    private let placeholder: () -> T

    public init(@ViewBuilder content: @escaping () -> WebImage,
                             @ViewBuilder placeholder: @escaping () -> T) {
        self.content = content
        self.placeholder = placeholder
    }

    public var body: some View {
        ZStack {
            if shouldShowImage {
                content()
            } else {
                placeholder()
            }
        }
        .onAppear {
            shouldShowImage = true
        }
        .onDisappear {
            shouldShowImage = false
        }
    }
}

then use

ScrollView {
    LazyVStack {
        ForEach(contents) { content in
            LazyReleaseableWebImage {
                WebImage(url: URL(string: content.url))
                    .placeholder {
                        placeholder(content.tag)
                    }
                    .onProgress(perform: onWebImageProgress)
                    .resizable()
            } placeholder: {
                placeholder(content.tag)
            }
            .scaledToFit()
        }
    }
}

seems does not cause the memory issue.

onevcat said the LazyVStack is buggy. So I’ll bring a List reproducible demo next time.

Thanks for your reply 😃

I finished the profile, no leaks and only one SDAnimatedImagePlayer. It crashed due to memory issue anyway.

I can upload the trace file to Mega, or full allocation summary screenshots instead?

Update: The .purgeable modifier doesn’t help.