Swift可以从异步void返回块返回值吗? [英] Can Swift return value from an async Void-returning block?

查看:398
本文介绍了Swift可以从异步void返回块返回值吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to create a function to check if user_id is already in my database.

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

However, observeSingleEventOfType is a API provided by 3rd party Firebase. It is defined to return Void.



  • (void)observeSingleEventOfType:(FEventType)eventType withBlock:(void(^)(FDataSnapshot * )block

错误:类型'Void'不符合协议'BooleanLiteralConvertible'

欣赏任何种类的帮助。

UPDATE

我尝试不同的方式:

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
}

不知怎的,它只是冻结在那里。我知道这种方法现在可能是偏离主题。

Somehow it just freeze there. I know this approach could be off-topic now. But please help.

推荐答案

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

You should employ asynchronous completion handler yourself:

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






在您修改的问题中,您演示了使用派遣组这个异步方法同步运行。 (信号量也经常用于相同的目的。)


In your revised question, you demonstrate the use of dispatch groups to make this asynchronous method behave synchronously. (Semaphores are also often used to the same ends.)

两个问题:


  1. 如果他们将完成处理程序分派给主队列,这将会死锁(在许多情况下,库会这样做来简化我们的生活),因为你巧合地阻塞了他们正在尝试的同一个线程使用。我不知道这是否是他们在这里做的,但很可能。

  1. This will deadlock if they dispatch their completion handler back to the main queue (and in many cases, libraries will do this to simplify life for us), because you're coincidentally blocking the very same thread they're trying to use. I don't know if that's what they've done here, but is likely.

如果您想确认这一点,请临时删除调度组,然后检查 NSThread.isMainThread 在主线程或不。

If you want to confirm this, temporarily remove dispatch group and then examine NSThread.isMainThread and see if it's running in main thread or not.

你永远不应该阻塞主线程。他们提供了一个异步接口有很好的理由,所以你应该在调用它时使用异步模式。不要对异步模式,而是拥抱它们。

You never should block the main thread, anyway. They provided an asynchronous interface for good reason, so you should use asynchronous patterns when calling it. Don't fight the asynchronous patterns, but rather embrace them.

这篇关于Swift可以从异步void返回块返回值吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆