Swift中如何等待异步函数返回结果?附代码问题示例
解决异步请求未完成就返回的问题
你的问题核心是fetchProfilesForList函数里的所有fetchProfile都是异步操作,函数会在这些异步请求返回结果前就执行到completion语句,导致返回空数组。可以通过DispatchGroup来等待所有异步请求完成后再返回结果,具体修改如下:
修改后的ViewModel代码
func addNoteToList(title: String, note: String) { guard let id = self.listID, let userID = profileID else { return } fm.fetchProfile(uid: userID) { [self] profile in print("FETCHED USER PROFILE FOR SHORTCUT") fm.fetchList(uid: id) { [self] list in print("FETCHED LIST FOR SHORTCUT") fetchProfilesForList(list: list) { profiles in print("users retuned \(profiles.count)") for p in profiles { print("ADD NOTE TO LIST SHORTCUT") // 创建Payment let note = Payment(title: title, note: note, user: p.uid) // 添加到列表并更新 var updatedList = list updatedList.notes.append(note) self.fm.updateList(updatedList) } } } } } func fetchProfilesForList(list: List, completion: @escaping ([Profile]) -> Void) { var groupProfiles: [Profile] = [] let dispatchGroup = DispatchGroup() // 处理管理员逻辑(如果当前用户不是管理员且在群组中) if list.admin != profileID, let currentProfileID = profileID, list.group.contains(currentProfileID) { print("IS NOT ADMIN and add to note") dispatchGroup.enter() fm.fetchProfile(uid: list.admin) { admin in print("FETCHED ADMIN") groupProfiles.append(admin) dispatchGroup.leave() } } // 遍历群组中的用户,获取除当前用户外的其他用户资料 for p in list.group { guard let currentProfileID = profileID, p != currentProfileID else { continue } dispatchGroup.enter() fm.fetchProfile(uid: p) { profile in print("profile \(profile.firstName)") groupProfiles.append(profile) dispatchGroup.leave() } } // 等待所有异步请求完成后,处理结果并返回 dispatchGroup.notify(queue: .main) { let uniqueUsers = groupProfiles.removeDuplicates() completion(uniqueUsers) } }
关键修改点说明
- 使用DispatchGroup:每个
fetchProfile调用前调用enter(),在回调完成后调用leave(),确保所有异步操作都完成后才执行后续逻辑。 - 修复变量错误:原代码中
people.append(admin)是笔误,改为添加到目标数组groupProfiles;原completion(p)修正为传入处理后的去重数组uniqueUsers。 - 可选值安全处理:用
guard let替代强制解包,避免潜在崩溃风险。 - 代码结构优化:将嵌套的
if let改为guard let,让代码逻辑更清晰易读。
额外提示
确保你的removeDuplicates()自定义方法是基于Profile的唯一标识(比如uid)来实现去重,避免重复添加同一用户的资料。
内容的提问来源于stack exchange,提问作者JUSDEV
相关产品推荐
相关产品推荐

