Reputation: 1659
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
What am I doing wrong?
Upvotes: 2
Views: 133
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