Search code examples
swiftxcode10ios12swift4.2optional-binding

Unwanted behaviour with optional binding evaluating optional(nil)


After updating xCode to version 10 (and swift 4.2), I have a strange behaviour on optional bindings

The code is below, and it ´s about reading json file, T is a generic type (here String)

// Are there values for configName ?
if let values = cfg[configName] as? [String: Any] {

    print("0 - values[langCode!] = ", values[langCode!] ?? "null")
    print("1 - values[langCode!] as? T = ", values[langCode!] as? T)

    // is there a value for langCode ?
    if let value = values[langCode!] as? T {
        print("2 - value to return= ", value)
        return value
    } else {
        print("3 - Do something else ")
    }
}

In xCode 9.4.1 and Swift 4.1 I have the following logs:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  nil
3 - Do something else 

That is what I want, values[langCode!] is nil and the cast also return nil so the else block is executed.

In xCode 10 with Swift 4.2, I have the following logs:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  Optional(nil)
2 - value to return=  nil

Here the if let block is executed even if values[langCode!] is "null".

One difference is that with swift 4.2 values[langCode!] as? T is an Optional(nil) and on Swift 4.1 values[langCode!] as? T is an nil.

I checked the changelog for version 4.2 and I could not see something that can explain that behaviour, I also checked that no changes have been done on JSONSerialization (used to serialize the json file)

Has someone also experienced that kind of thing when switching to Swift4.2 ? Does someone have an explanation ? And a work around ?

In this kind of code what is the advantage to use optional binding ? would it be bad to write if (values[langCode!] != nil) {... instead of the optional binding ?

Thanks


Solution

  • I answer my question since the correct answer has been given in comments.

    The difference observed between Swift4.1 and Swift4.2 is due to an intentional change. @Hamish explains everything in the answer is done here: stackoverflow.com/q/52446097/2976878