如何在Swift的validateFields函数中返回Firebase QuerySnapshot异步查询结果
问题根源
你当前的写法无法拿到正确的返回值,核心原因是isUnique是异步执行的函数,它的回调闭包不会阻塞validateFields的执行流程:在你调用isUnique之后,代码会立刻往下执行print和return逻辑,此时回调里给retVal赋值的代码还没运行,所以你拿到的永远是初始值false。异步函数的结果不可能直接作为同步函数的返回值返回,必须调整实现方案。
方案1:将validateFields改造为带回调的异步函数(兼容所有iOS版本)
把原来同步返回Bool的逻辑改成通过闭包回调传递校验结果,代码示例如下:
func validateFields(completion: @escaping (Bool) -> Void) { // 其他前置同步判断语句 // 示例:密码为空直接返回校验不通过 if passwordTextField.text?.isEmpty ?? true { errorLabel.text = "密码不能为空" completion(false) return } // ... 其余同步判断逻辑 guard let username = usernameTextField.text, !username.isEmpty else { errorLabel.text = "用户名不能为空" completion(false) return } // 调用异步唯一性校验,在回调中返回最终结果 isUnique { [weak self] isUnique in guard let self = self else { return } print("THIS IS THE RET VALUE: " + String(isUnique)) if !isUnique { self.errorLabel.text = "用户名已存在" completion(false) return } self.errorLabel.text = " " completion(true) } }
调用方式调整为:
validateFields { [weak self] isValid in guard let self = self else { return } if isValid { // 校验通过后的业务逻辑,比如提交表单、跳转页面 } }
方案2:使用async/await实现(支持iOS 15+/macOS 12+及更高版本)
如果项目适配版本允许,可以用Swift Concurrency特性把异步逻辑转成同步等待的写法,代码更简洁:
// 先将回调形式的isUnique封装为async版本 func isUnique() async -> Bool { await withCheckedContinuation { continuation in isUnique { bool in continuation.resume(returning: bool) } } } // 异步版本的校验函数 func validateFields() async -> Bool { // 其他前置同步判断逻辑 if passwordTextField.text?.isEmpty ?? true { errorLabel.text = "密码不能为空" return false } // ... 其余同步判断逻辑 guard let username = usernameTextField.text, !username.isEmpty else { errorLabel.text = "用户名不能为空" return false } // 等待异步校验结果 let isUnique = await isUnique() print("THIS IS THE RET VALUE: " + String(isUnique)) if !isUnique { errorLabel.text = "用户名已存在" return false } errorLabel.text = " " return true }
调用方式调整为:
Task { @MainActor in let isValid = await validateFields() if isValid { // 校验通过后的业务逻辑 } }
内容的提问来源于stack exchange,提问作者EAO123
相关产品推荐
相关产品推荐

