e.iluf
e.iluf

Reputation: 1659

image is not loading on swiftui collectionview

I'm trying to load an image but the image is not loading.

I setup my image loader

class ImageLoader: ObservableObject {
@Published var image: UIImage?
private let url: URL
private var cancellable: AnyCancellable?

init(url: URL) {
    self.url = url
}

 deinit {
       cancellable?.cancel()
   }

   func load() {
       cancellable = URLSession.shared.dataTaskPublisher(for: url)
           .map { UIImage(data: $0.data) }
           .replaceError(with: nil)
           .receive(on: DispatchQueue.main)
           .assign(to: \.image, on: self)
   }
   
   func cancel() {
       cancellable?.cancel()
   }
 }

and then AsyncImage struct

struct AsyncImage<Placeholder: View>: View {
@ObservedObject private var loader: ImageLoader
private let placeholder: Placeholder?

init(url: URL, placeholder: Placeholder? = nil) {
    loader = ImageLoader(url: url)
    self.placeholder = placeholder
}

var body: some View {
    image
        .onAppear(perform: loader.load)
        .onDisappear(perform: loader.cancel)
}

private var image: some View {
    placeholder
}
}





struct ProductSearhView: View {
 @ObservedObject var model: SearchResultViewModel
var body: some View{
    NavigationView {
         List {
                ForEach(0 ..< Global.productArry.count) { value in
                     CollectionView(model: self.model, data: Global.productArry[value])
                }
                
         }.navigationBarTitle("CollectionView")
    }


 }

}



struct CollectionView: View {
 @ObservedObject var model: SearchResultViewModel

let data: Product
    var body: some View {
        VStack {
            HStack {
                 
                Spacer()
                    AsyncImage(url: URL(string: self.data.productImageUrl)!, placeholder: Text("Loading ...")
                    ).aspectRatio(contentMode: .fit)
                Spacer()
               
            }
            HStack {
                Spacer()
                Text(self.data.name)
                Spacer()
                
                 }
        }.onAppear(perform:thisVal)
     }

func thisVal (){
    
    print(self.data.productImageUrl)
    // https://i5.walmartimages.com/asr/113d660f-8b57-4ab8-8cfa-a94f11b121aa_1.f6bad4b281983e164dcf0a160571e886.jpeg?odnHeight=180&odnWidth=180&odnBg=ffffff
    
}
}

Everything else works fine except the image loading. The image only shows the placeholder and not the image. Sample image url to load is this

https://i5.walmartimages.com/asr/113d660f-8b57-4ab8-8cfa-a94f11b121aa_1.f6bad4b281983e164dcf0a160571e886.jpeg?odnHeight=180&odnWidth=180&odnBg=ffffff

What am I doing wrong?

Upvotes: 2

Views: 133

Answers (1)

Tristan Warner-Smith
Tristan Warner-Smith

Reputation: 9771

It looks like you're missing an Image. Where you have:

private var image: some View {
    placeholder
}

You're only ever going to have a placeholder. If you change it to be:

private var image: some View {
    Group {
        if loader.image != nil {
            Image(uiImage: loader.image!)
                .resizable()
        } else {
            placeholder
        }
    }
}

That should mean that if the ImageLoader has successfully loaded the image it'll show the Image with the loaded uiImage, otherwise it'll show the placeholder.

Upvotes: 2

Related Questions