Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift能否从异步无效返回块返回值?_Swift_Return_Closures_Firebase_Objective C Blocks - Fatal编程技术网

Swift能否从异步无效返回块返回值?

Swift能否从异步无效返回块返回值?,swift,return,closures,firebase,objective-c-blocks,Swift,Return,Closures,Firebase,Objective C Blocks,我想创建一个函数来检查用户id是否已经在我的数据库中 class func checkIfUserExsits(uid:String) -> Bool { userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value, withBlock: { (snapShot: FDataSnapshot!) -> Void in if snapShot.value is NSNull

我想创建一个函数来检查用户id是否已经在我的数据库中

class func checkIfUserExsits(uid:String) -> Bool {
    userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value, withBlock: { (snapShot: FDataSnapshot!) -> Void in
                if snapShot.value is NSNull {
                    return false
                } else {
                    return true
                }
    })
}
但是,
observeSingleEventOfType
是第三方Firebase提供的API。它被定义为返回
Void

  • (void)observeSingleEventOfType:(FEventType)eventType with block:(void(^)(FDataSnapshot*snapshot))block
错误:
类型“Void”不符合协议“BooleanLiteralConvertible”

感谢任何帮助


更新

我正在尝试另一种方式:

class func checkIfExist(uid: String) -> Bool {
    var answer:Bool = false
    var text:String = "not yet completed"
    let queue = dispatch_group_create()
    dispatch_group_enter(queue)
        userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value, withBlock: { (snapShot: FDataSnapshot!) -> Void in
                if snapShot.value is NSNull {
                    text = "This is a new user"
                    answer  = false
                    dispatch_group_leave(queue)
                } else {
                    text = "Found the user in Firebase"
                    answer = true
                    dispatch_group_leave(queue)
                }
        })
    dispatch_group_wait(queue, DISPATCH_TIME_FOREVER)
    println(text)
    return answer
}

不知怎的,它只是冻结在那里。我知道这种方法现在可能会偏离主题。但是请提供帮助。

您应该自己使用异步完成处理程序:

class func checkIfUserExists(uid: String, completionHandler: (Bool) -> ()) {
    userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value) { snapShot in
        if snapShot.value is NSNull {
            completionHandler(false)
        } else {
            completionHandler(true)
        }
    }
}
你可以这样称呼它:

MyClass.checkIfUserExists(uid) { success in
    // use success here
}

// but not here

在修改后的问题中,您演示了如何使用调度组使此异步方法同步运行。(信号量也经常用于相同的目的。)

两个问题:

  • 如果他们将其完成处理程序分派回主队列(在许多情况下,库会这样做以简化我们的生活),这将导致死锁,因为您恰好阻塞了它们试图使用的同一个线程。我不知道他们在这里是否就是这么做的,但很有可能

    若要确认这一点,请临时删除调度组,然后检查
    NSThread.isMainThread
    ,查看它是否在主线程中运行

  • 无论如何,您永远不应该阻塞主线程。它们提供了一个异步接口是有充分理由的,所以在调用它时应该使用异步模式。不要反对异步模式,而是接受它们


  • 谢谢我想知道是否还有其他不那么冗长的方法来做这件事。我不喜欢我的项目全部嵌套在完整块中的完整块中。非常感谢Rob。我知道我可能用了一种非常错误的方式,但我仍然想尝试一下。正如您所说,我正在尝试取消该功能的异步。我不熟悉信号灯。我试着用dispatch_group_wait代替。请参阅我问题的更新。如果他们将完成处理程序分派回主队列(在许多情况下,库将这样做以简化我们的生活),您将死锁,阻塞主线程,等待库将完成处理程序分派到您正在阻塞的同一线程。我不知道他们在这里是否就是这么做的,但很有可能。如果要确认,请暂时删除调度组,然后检查
    NSThread.isMainThread
    。但是,再一次,我强烈建议不要仅仅因为您不太习惯使用闭包和异步模式而阻塞主线程。