在SwiftUI中切换视图后,Firebase图像为空

时间:2019-12-01 20:16:43

标签: ios swift firebase firebase-storage swiftui

我正在尝试显示Firebase中存储的对象列表中的图像。最初,图像可以很好地加载,但是如果我切换到其他视图并返回到列表视图,则图像将不再加载。

Gif of the described bug

在两次加载尝试中,图像数据似乎都按预期方式保存: here

下面是我的图像加载器代码,该图像加载器使用URL从Firebase Storage中获取图像,并使用包含图像的列表行。

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)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我解决此问题的方法是创建一个自定义ImageView并处理此视图中的图像加载。我通过遵循this tutorial来解决这个问题,并意识到那是我错过的一步。如果有人能解释为什么使用内置SwiftUI Image()会导致此问题,我将非常感激。

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
            }
        }
    }
}