Reputation: 41
I'm trying to display images from a list of objects stored in Firebase
. Initially the image loads fine, but if I switch to a different view and return to the list view the image never loads again.
The image data seems to be saved as expected on both load attempts: here
Below is my code for the image loader, which uses a url to fetch the images from Firebase Storage, and the list row that contains the image.
ImageLoader.swift
import Foundation
import SwiftUI
import Firebase
import FirebaseFirestore
class ImageLoader: ObservableObject {
@Published var dataIsValid = false
var data:Data?
func loadImage(url: String) {
let imageRef = Storage.storage().reference(forURL: url)
imageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print("\(error)")
}
guard let data = data else { return }
DispatchQueue.main.async {
print(self.dataIsValid)
self.dataIsValid = true
self.data = data
}
}
}
func imageFromData() -> UIImage {
UIImage(data: self.data!)!
}
}
ListRow.swift
import SwiftUI
import Combine
struct EventRow: View {
@ObservedObject var imageLoader = ImageLoader()
var imageUrl: String
var body: some View {
HStack {
Image(uiImage: self.imageLoader.dataIsValid ? self.imageLoader.imageFromData() : UIImage())
.resizable()
.frame(width: 100.0, height: 140.0)
.background(Color.gray)
.clipShape(RoundedRectangle(cornerRadius: 5.0))
}
.onAppear {
self.imageLoader.loadImage(url: self.imageUrl)
}
}
}
Upvotes: 1
Views: 1006
Reputation: 41
The way I fixed this was by creating a custom ImageView and handling the image loading within this view. I figured this out by following this tutorial and realized that was the step I was missed. If anyone can explain why using the built-in SwiftUI Image()
causes this issue I would really appreciate it.
ListRow.swift
import SwiftUI
struct ListRow: View {
var imageUrl: String
var body: some View {
HStack {
FBURLImage(url: imageUrl)
}
}
}
FBURLImage.swift
import SwiftUI
struct FBURLImage: View {
@ObservedObject var imageLoader: ImageLoader
init(url: String) {
imageLoader = ImageLoader()
imageLoader.loadImage(url: url)
}
var body: some View {
Image(uiImage:
imageLoader.data != nil ? UIImage(data: imageLoader.data!)! : UIImage())
.resizable()
.frame(width: 100.0, height: 140.0)
.background(Color.gray)
.clipShape(RoundedRectangle(cornerRadius: 5.0))
}
}
ImageLoader.swift
import Foundation
import SwiftUI
import Firebase
import FirebaseFirestore
class ImageLoader: ObservableObject {
@Published var data: Data?
func loadImage(url: String) {
let imageRef = Storage.storage().reference(forURL: url)
imageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print("\(error)")
}
guard let data = data else { return }
DispatchQueue.main.async {
self.data = data
}
}
}
}
Upvotes: 3