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

Swift中Firestore getDocuments函数无法终止、无法返回数据问题

问题根源

Firestore的getDocuments是异步网络请求API,你写的同步返回[Post]的逻辑本身就不成立:

  • 调用getDocuments后,系统会把网络请求放到后台执行,不会阻塞当前代码流程等结果返回
  • 你用来组装数据的闭包是逃逸闭包,会在网络请求完成后才执行,远晚于外层函数自身的返回时机
  • 你遇到的print("test")不触发,基本是死锁导致:如果在主线程调用该函数,又用同步方式堵线程等结果,Firestore默认要把回调派发到主线程,主线程被占死就会两边互相等待卡死,自然走不到后续代码。就算不死锁,你外层return拿到的也永远是空数组,因为函数返回时闭包里的组装逻辑还没执行。
修改方案

把同步返回改成completion回调模式,用逃逸闭包把异步拿到的数组回传给调用方:

static func getData(completion: @escaping ([Post]) -> Void) {
    let db = Firestore.firestore()
    db.collection("Posts").getDocuments { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error retrieving snapshots \(error!)")
            completion([])
            return
        }
        
        var posts = [Post]()
        for document in snapshot.documents {
            let data = document.data()
            posts.append(Post(
                t: data["title"] as? String ?? "",
                a: data["author"] as? String ?? "",
                pm: data["priceMax"] as? Double ?? 0.0,
                c: data["content"] as? String ?? ""
            ))
            print("New Post... ")
            print(data)
            print(posts.count)
            print(posts[0].title)
        }
        // 数据组装完成后通过闭包回调结果
        completion(posts)
    }
}
调用方式

不要直接接返回值,在completion闭包中处理拿到的结果,涉及UI更新必须切回主线程:

// 调用示例
Post.getData { [weak self] posts in
    print("获取到\(posts.count)条Post数据")
    // UI操作切主线程
    DispatchQueue.main.async {
        // 比如刷新列表、给数据源赋值
        self?.postList = posts
        self?.tableView.reloadData()
    }
}

内容的提问来源于stack exchange,提问作者Ari Steinfeld

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:45:33