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
相关产品推荐
相关产品推荐

