无合并:在 Swift 中使用可选类型作为默认值

nil coalescing: Using optional types as default value in Swift

我有这个:

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 = [=14=] as? [String: AnyObject] ??  {
            println(result)
        }
    }

这取决于您所说的 "matter" 是什么意思。它会起作用。它可能不是你想要的 - 如果 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 可能比您想知道的更多,但简而言之:结果必须在编译时固定为特定类型,而不管 ab 处于运行时。由于 b 是可选的,因此 a! 隐式包装在可选中以使两种类型兼容。这么说吧——如果结果不是可选的,而 bnil,结果会是什么?

请记住,您可以链接 ??,这样您就可以在末尾放置第三个非可选值,这将使结果成为非可选值。

这是零合并。

如果 b 不是可选的:
a ?? b 将 return 展开 a,如果 a 不为零。如果 a 为零,它将 return b.

如果 b 是非可选的:
a ?? b 将 return a,如果 a 不为零。如果 a 为零,它将 return b.

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

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