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

查看:25
本文介绍了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 是由 3rd 方 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 *snapshot ))block

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

感谢任何形式的帮助.

更新

我正在尝试不同的方式:

I am trying a different way:

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 (ie, escaping) completion handler yourself:

class func checkIfUserExists(uid: String, completion: @escaping (Bool) -> Void) {
    userRef.childByAppendingPath(uid).observeSingleEventOfType(.Value) { snapShot in
        if snapShot.value is NSNull {
            completion(false)
        } else {
            completion(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天全站免登陆