Swift中完成处理程序添加数据后全局数组仍为空的问题
问题分析与解决方案
问题根源
你的代码核心问题出在异步操作的执行顺序上:
fetchActiveUsers函数中,循环调用UserProfile.getUserProfileData是异步的Firestore读取操作,但你在循环结束后立刻调用了completionHandler()。此时所有getUserProfileData的请求还没完成,activeUsers数组还没被填充元素,所以viewDidLoad里的闭包打印出的数组长度是0。
修复方案
使用DispatchGroup跟踪所有异步请求的完成状态,等所有用户数据都获取并添加到数组后,再调用completionHandler。修改后的fetchActiveUsers代码如下:
func fetchActiveUsers(using completionHandler: @escaping () -> Void) { let myCompletionHandler: (UserProfile?) -> Void = { theUser in guard let user = theUser else { return } // 安全解包,避免强制解包崩溃 self.activeUsers.append(user) print("Count in fetchActiveUsers myCompletionHandler", self.activeUsers.count) } self.chatsDocRef!.getDocument { document, error in if let error = error as NSError? { print("Error getting document: \(error.localizedDescription)") completionHandler() // 出错也要调用completion,避免界面卡住 return } guard let document = document, let data = document.data(), let activeUserUIDS = data["users"] as? [String] else { completionHandler() return } self.activeUserUIDS = activeUserUIDS let dispatchGroup = DispatchGroup() // 创建调度组 for uid in activeUserUIDS { print("Retrieving document for user ID: ", uid) let userDocRef = Firestore.firestore().collection("users").document(uid) dispatchGroup.enter() // 标记一个异步任务开始 UserProfile.getUserProfileData(userDocRef) { theUser in myCompletionHandler(theUser) dispatchGroup.leave() // 标记这个异步任务完成 } } // 等待所有异步任务完成后,在主线程执行completion dispatchGroup.notify(queue: .main) { completionHandler() // 此时activeUsers已完全填充 } } }
额外优化建议
- 杜绝强制解包(比如
theUser!),用guard let或if let做安全解包,避免潜在崩溃。 loadActiveUsersTableView中的表格布局代码可以提前在viewDidLoad初始化阶段完成,不用等到数据加载后再添加,只需要在数据准备好后调用reloadData()刷新表格即可。
内容的提问来源于stack exchange,提问作者BiggRojo
相关产品推荐
相关产品推荐

