nil coalescing:在Swift中使用可选类型作为默认值

时间:2015-01-04 16:03:57

标签: swift optional null-coalescing

我有这个:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

        dispatch_async(queue, {
            if let data = NSURLConnection.sendSynchronousRequest(self.buildRequestForVenueLocation(location, identifier), returningResponse: &response, error: &error) {
                let responseDictionary: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .allZeros, error:&error) ?? error?.localizedDescription
                dispatch_async(dispatch_get_main_queue(), {
                    completion(venues: responseDictionary, error: error)
                })
            } else {
                println("There was a problem with the request...")
            }
        })

我的问题特别关注这一行:

let responseDictionary: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .allZeros, error:&error) ?? error?.localizedDescription

这是nil coalescing的正确用法吗?

根据Apple的文档,这是等效的:

a != nil ? a! : b

如果a为nil,则返回b,但如果b是可选类型,则确实有意义吗?

修改

如果有人想知道,这就是我调用这个函数时的样子:

v.performVenueLocationRequest(l.location, identifier: "4d4b7105d754a06374d81259") {
        if let result = $0 as? [String: AnyObject] ?? $1 {
            println(result)
        }
    }

2 个答案:

答案 0 :(得分:1)

这取决于你的意思"问题"。它会工作。它可能不是你想要的 - 如果b是可选的,那么结果也是可选的,即使a有值,它仍然无法解开:

let a: Int? = 2
let b: Int? = 3
let c = i ?? j
// c is {Some 2}

let i: Int? = nil
let j: Int? = 3
let k = i ?? j
// k is {Some 3}

请参阅this article可能超过您想知道的原因,但简而言之:结果必须在编译时作为特定类型修复,而不管a和{{的值是什么1}}在运行时。由于b是可选的,b隐式包含在可选项中,以使两种类型兼容。这样说 - 如果结果不是可选的,而a!b,结果会是什么?

请记住,您可以链接nil,这样您就可以在结尾放置第三个值,这个值不是可选的,会使结果成为非可选的。

答案 1 :(得分:0)

这是零合并。

如果b不是可选的:
 如果a不是零,a ?? b将返回未包装的a。如果a为零,则返回b。

如果b不是可选的:
 如果a不是零,a ?? b将返回a。如果a为零,则返回b。

此代码可以使用。 但是因为无论如何你都是单独捕获错误,我建议将responseDictionary留作nil,而不是将其分配给error.localDescription(如果失败)。这只是更好的设计。如下所示。

let responseDictionary: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .allZeros, error:&error)