0

I created a custom view, NetworkImage, to load image asynchronously.

import Combine
import SwiftUI

struct NetworkImage<Placeholder: View>: View {
    @StateObject private var viewModel = NetworkImageViewModel()
    let url: String?
    let placeholder: Placeholder
    let saveLocally:Bool
    
    init(_ url: String?, @ViewBuilder placeholder: () -> Placeholder, saveLocally:Bool = false) {
        self.url = url
        self.placeholder = placeholder()
        self.saveLocally = saveLocally
    }
    
    func loadImage(_ url:String?)  {
        if let url = url {
            viewModel.loadImage(from: url, saveLocally: saveLocally)
        }
    }
    
    var body: some View {
        Group {
            if let uiImage = viewModel.image {
                Image(uiImage: uiImage)
                    .resizable()
            } else {
                placeholder
            }
        }
        .onAppear {
            if let url = url {
                viewModel.loadImage(from: url, saveLocally: saveLocally)
            }
        }
    }
}

I use this in my views and it works really well. But now I would like to be able to replace the image with a new one each time the url change. How can I do that? How can I pass a @Published property of my view's viewmodel to this NetworkImage view and make it work?

Thanks

1 Answer 1

1

Use the onChange modifier to see if the url parameter has changed:

struct NetworkImage<Placeholder: View>: View {
    @StateObject private var viewModel = NetworkImageViewModel()
    let url: String?
    let placeholder: Placeholder
    let saveLocally:Bool = false
    
    func loadImage(_ url:String?)  {
        if let url = url {
            viewModel.loadImage(from: url, saveLocally: saveLocally)
        }
    }
    
    var body: some View {
        Group {
            if let uiImage = viewModel.image {
                Image(uiImage: uiImage)
                    .resizable()
            } else {
                placeholder
            }
        }
        .onAppear {
            self.loadImage(url)
        }
        .onChange(of: url) { url in
            self.loadImage(url)
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Just one thing I don't understand: this does not work if I use the value of self.url in loadImage(). Same for self.saveLocally. I would like to listen to changes of the saveLocally and use it with loadImage(url, saveLocally) but the value of saveLocally does not change at the right time (seems a bit random)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.