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'
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
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
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...).
The release notes of XCode 6 Beta 5 state the following:
Optionals no longer conform to the BooleanType (formerly LogicValue) protocol, so they may no longer be used in place of boolean expressions (they must be explicitly compared with v != nil). This resolves confusion around Bool? and related types, makes code more explicit about what test is expected, and is more consistent with the rest of the language.
Note that ImplicitlyUnwrappedOptional still includes some BooleanType functionality. This !issue will be resolved in a future beta. (17110911)!
This means your previous approach should work now without any issues, just go back to it:
if (launchOptions != nil && launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey] != nil) {
// some code
}
As @Sulthan figured out, this is a bug in the current beta release of the Swift compiler. But note that an optional is itself a LogicValue
that can be tested for its boolean value. So you can simply write
if launchOptions && launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] {
// ...
}
without comparing to nil
.
This compiles for me but I'm not sure if it works as intended:
if launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey] !== nil {}
This is most likely a side-effect by the change of nil
to a literal in beta 3:
• nil is now a literal in the language, not a global constant of _Nil type. This change resolved a number of problems with nil; eg nil in a collection, nil converting to Any, etc. Types can now indicate that they are nil compatible by conforming to the NilLiteralConvertible protocol. (16951729)
For some reason it just complains when its an optional returned from indexing a dictionary, I have a feeling this will be fixed in the future. Submit a bug report though!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.