You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVVM项目中如何从Firebase返回数组并正确存储到变量

针对你的两个MVVM+Firebase数据返回问题的解决方案

咱们先从第一个核心问题说起:如何正确返回异步数据并存储到变量中

Firebase的数据库/存储操作都是异步执行的——也就是说,当你调用getFirebaseData这类方法时,代码不会等待网络请求完成就继续往下走了。如果直接尝试同步返回数据,你大概率会拿到空数组,因为数据还没从服务器拉回来。

正确的做法是用**闭包(Completion Handler)**或者Combine框架来处理异步回调,等数据真正准备好之后再把它传递给调用者并存储到变量里。闭包是最直观的方案,尤其适合刚迁移到MVVM的场景。


接下来针对你的第二个具体场景:把仓库类中Firebase循环生成的数组返回给MyCollectionViewClass

我会给你一步步的代码示例,贴合你已经有的结构:

第一步:修改仓库类的getFirebaseData方法,添加闭包参数

首先在你的Firebase仓库类里,把原来的方法改成带闭包的形式,闭包用来返回最终的[Recipe]数组:

class FirebaseReference {
    // 假设这是你的仓库类
    func getFirebaseData(with stringParam: String, completion: @escaping ([Recipe]) -> Void) {
        // 这里是你的Firebase查询逻辑,比如从Firestore获取数据
        let db = Firestore.firestore()
        db.collection("your-collection-path").whereField("someField", isEqualTo: stringParam).getDocuments { snapshot, error in
            guard let documents = snapshot?.documents, error == nil else {
                print("获取数据失败:\(error?.localizedDescription ?? "未知错误")")
                completion([]) // 出错时返回空数组,也可以根据需求返回错误信息
                return
            }
            
            var recipeArray = [Recipe]()
            // 遍历Firebase返回的文档,生成Recipe数组
            for doc in documents {
                if let recipe = try? doc.data(as: Recipe.self) { // 假设Recipe实现了Codable
                    recipeArray.append(recipe)
                }
            }
            
            // 数据准备好后,通过闭包返回
            completion(recipeArray)
        }
    }
}

第二步:在MyCollectionViewClass中调用方法并存储数据

在你的MyCollectionViewClass里,调用仓库方法时,通过闭包拿到返回的数组,赋值给imageArray,然后刷新CollectionView:

class MyCollectionViewClass: UICollectionViewController {
    var imageArray = [Recipe]()
    let firebaseReference = FirebaseReference() // 初始化仓库类实例
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 调用仓库的方法,传入参数并处理返回数据
        firebaseReference.getFirebaseData(with: self.dataRecieverStringCollectionView) { [weak self] fetchedRecipes in
            guard let self = self else { return }
            // 将返回的数组存储到变量中
            self.imageArray = fetchedRecipes
            // 刷新CollectionView,因为数据源更新了
            self.collectionView.reloadData()
        }
    }
    
    // 其他CollectionView数据源方法...
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageArray.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCellClass
        let recipe = imageArray[indexPath.item]
        // 用recipe配置cell的UI...
        return cell
    }
}

关键注意点

  • 用[weak self]避免循环引用:在闭包中捕获self时,加上弱引用可以防止内存泄漏,这在ViewController中尤其重要。
  • 处理错误情况:示例中出错时返回空数组,你也可以把闭包改成@escaping (Result<[Recipe], Error>) -> Void,这样能更优雅地传递错误信息,调用者可以通过switch处理成功和失败的情况。
  • 确保Recipe模型实现Codable:Firestore的doc.data(as:)方法需要模型遵守Codable协议,这样才能自动解析文档数据到模型对象中。

内容的提问来源于stack exchange,提问作者Joakim Sjöstedt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:43:21