等待完成处理程序完成后再返回

Wait for completion handler to finish before returning

提问人:David 提问时间:9/29/2022 更新时间:9/29/2022 访问量:771

问:

    func checkUsername(username: String) -> Bool {
        var avalible = true
        
        Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value, with: { snapshot in
            if snapshot.exists() {
                print("exists")
                avalible = false
            }
        })
        
        return available
    }

我正在尝试检查用户名是否存在。
我已经尝试了多种方法,但似乎该函数总是在完成处理程序完成之前返回,并且即使用户名已被占用,也总是给出相同的输出 (true)。

是否有人知道如何在返回“可用”变量之前先“等待”完成处理程序完成?

带有答案的解释会很好。
谢谢。

iOS Swift Firebase Closures CompletetionHandler

评论


答:

0赞 Erik Terwan 9/29/2022 #1

这是因为 Firebase 操作是异步的,您不能简单地将其转换为同步操作而不阻塞线程。

看看如何在 Swift 中创建带有完成处理程序的函数?

在不使用新的 async/await 语法的情况下,解决此问题的正确方法是自己使用完成处理程序。

func checkUsername(username: String, completion: @escaping (Bool) -> ()) {
    Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value) { snapshot in
         completion(!snapshot.exists())
    }
}

// To use:
checkUsername(username: "foo") { exists in 
    print("exists? ", exists)
}

评论

0赞 Duncan C 9/29/2022
人们不会简单地从异步函数返回结果:imgflip.com/i/6v4w6c
2赞 vadian 9/29/2022 #2

不能从异步任务返回某些内容。您的代码(带有固定的拼写错误)甚至在数据库请求启动之前就返回。true

也许有一个原生的 async/await 版本,但无论如何你都可以使用observeSingleEventContinuation

func checkUsername(username: String) async -> Bool {
    return await withCheckedContinuation { continuation in
        Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value, with: { snapshot in
            continuation.resume(returning: !snapshot.exists())
        })
    }
}

并称它为

Task {
   let isAvailable = await checkUsername(username: "Foo")

}

评论

0赞 David 9/29/2022
谢谢,我以前确实尝试过这个,但有两个不同的延续,这就是为什么我感到困惑并且它不起作用。