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

SwiftUI项目中无法将Firebase多集合拉取数据添加到新数组

问题原因

Firestore 的 addSnapshotListener 是异步执行的操作,你在视图的 onAppear 中按顺序调用三个拉取方法后直接执行 combineGames 时,Firebase 的网络请求还未完成,三个分类数组 cardsMenu/diceMenu/miscellaneuosMenu 还处于初始空值状态,合并后自然得到空数组。

最简解决方案

利用 Combine 框架自动监听三个分类数组的变化,自动合并生成 allGames,无需手动调用合并方法,适配实时数据更新的场景:

  1. 修改 SearchController 代码:
import Foundation
import SwiftUI
import Firebase
import Combine // 导入Combine框架

class SearchController: ObservableObject {
    @Published var allGames = [GameModel]()
    @Published var cardsMenu = [GameModel]()
    @Published var diceMenu = [GameModel]()
    @Published var miscellaneuosMenu = [GameModel]()

    private var db = Firestore.firestore()
    private var cancellables = Set<AnyCancellable>() // 存储订阅
    
    init() {
        // 合并三个@Published属性的变化,自动生成allGames
        Publishers.CombineLatest3($cardsMenu, $diceMenu, $miscellaneuosMenu)
            .map { cardList, diceList, miscList in
                // 直接数组合并,不用循环append
                cardList + diceList + miscList
            }
            .assign(to: \.allGames, on: self)
            .store(in: &cancellables)
    }

    // 三个fetch方法保持原有代码不变
    func fetchCardGamesData() {/*原有代码*/}
    func fetchDiceGamesData() {/*原有代码*/}
    func fetchMiscGamesData() {/*原有代码*/}
    
    // combineGames方法可以直接删除
}
  1. 修改视图 onAppear 逻辑,删除手动合并调用:
.onAppear(){
    self.allGames.fetchCardGamesData()
    self.allGames.fetchDiceGamesData()
    self.allGames.fetchMiscGamesData()
    // 移除 self.allGames.combineGames() 调用
}
  1. 可选优化:如果你的项目最低支持iOS 14+,将视图中 SearchController 的声明从 @ObservedObject 改为 @StateObject,避免视图重绘时对象被意外销毁导致数据丢失:
@StateObject var allGames = SearchController()
其他注意事项

如果不需要监听Firestore的实时数据变化,可以把 addSnapshotListener 替换为 getDocuments 只拉取一次数据,减少不必要的性能消耗和内存占用。


内容的提问来源于stack exchange,提问作者Nicolaj Spiegelhauer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:18:03