Search code examples
swiftoption-typenull-coalescing

nil coalescing: Using optional types as default value in Swift


I have this:

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...")
            }
        })

My question is regarding this line in particular:

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

Is this correct usage of nil coalescing?

According to Apple's documentation this is the equvivalent:

a != nil ? a! : b

If a is nil, b is returned, but does is matter if the b is an optional type?

EDIT

In case anyone was wondering, here's what it looks like when I call the function:

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

Solution

  • It depends what you mean by "matter". It will work. It just might not be what you want - if b is optional, then the result will also be optional i.e. even if a has a value it still won't be unwrapped:

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

    versus:

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

    See this article for probably more than you want to know about why, but in short: the result must be fixed as a specific type at compile time regardless of what the values of a and b are at runtime. Since b is an optional, a! is implicitly wrapped in an optional to make the two types compatible. Put it this way – if the result were not optional, and b were nil, what would the result be?

    Bear in mind you can chain ?? so you could put a third value on the end that isn't optional that would make the result non-optional.