Swift (beta 3) "NSDictionary? does not conform to protocol 'Equatable'"

ios, nsdictionary, swift

Solution

There is a regression in Beta 3 causing that `Optional<T>` cannot be compared with `nil` if `T` is not `Equatable` or `Comparable`.

It's a bug caused by the removal of the `_Nil` type for which the equality operators were defined. `nil` is now a literal. The bug has been confirmed by Chris Lattner on Apple Dev Forums

Some workarounds:

You can still use `.getLogicValue()`

if launchOptions.getLogicValue() && ... {

or directly

if launchOptions && ... { //calls .getLogicValue()

or you can use the "Javascript object to boolean" solution

var bool = !!launchOptions

(first `!` calls the `getLogicValue` and negates, the second `!` negates again)

or, you can define those equality operators by yourself until they fix it:

//this is just a handy struct that will accept a nil literal
struct FixNil : NilLiteralConvertible {
    static func convertFromNilLiteral() -> FixNil {
        return FixNil()
    }
}

//define all equality combinations
func == <T>(lhs: Optional<T>, rhs: FixNil) -> Bool {
    return !lhs.getLogicValue()
}

func != <T>(lhs: Optional<T>, rhs: FixNil) -> Bool {
    return lhs.getLogicValue()
}

func == <T>(lhs: FixNil, rhs: Optional<T>) -> Bool {
    return !rhs.getLogicValue()
}

func != <T>(lhs: FixNil, rhs: Optional<T>) -> Bool {
    return rhs.getLogicValue()
}

Example:

class A {
}

var x: A? = nil

if x == nil {
    println("It's nil!")
}
else {
    println("It's not nil!")
}

However, this workaround might cause other subtle problems (it probably works similarily to the `_Nil` type in Beta 2 which was removed because it was causing problems...).

Problem

I've had a fair few warnings and errors in my Swift code since updating to the latest Xcode 6 DP3. Most have been resolved by adopting the newly changed syntax however there is one error which seems strange. The following code gives the error `Type 'NSDictionary?' does not conform to protocol 'Equatable'`: ``` if (launchOptions != nil && launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey] != nil) { ``` Does anyone have a solution? I'm probably overlooking something simple here..! Thanks

Original source