I have two AnyObject?
variables that I would like to compare for reference equality:
var oldValue: AnyObject?
var newValue: AnyObject?
...
if oldValue != newValue {
changed = true
}
This doesn't work though, as I apparently cannot compare two optionals directly. I want the behavior as if I were comparing id
s in Objective-C, that is:
true
if both are nil
true
if both have a value and the values are also equalfalse
otherwiseIs there an elegant way to write this in Swift (ideally without having to write a custom extension)?
This is the best I've come up with:
if !(oldValue != nil && newValue != nil && oldValue == newValue)
Not very pretty. :(
The difference between == and === in Swift is: == checks if two values are equal. === checks if two objects refer to the same object.
Optional types or Optionals in Swift You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn't a value at all.
Optionals are a fundamental part of swift coding. Keeping it simple, we can say that optionals help us to separate good code from bad code and hence prevent crashes. Different programming languages uses different preventive measures to avoid a crash. But most of them are helpless in most of the cases.
Optionals say either "there is a value, and it equals x" or "there isn't a value at all". An Optional is a type on its own, actually one of Swift 4's new super-powered enums. It has two possible values, None and Some(T), where T is an associated value of the correct data type available in Swift 4.
Assuming you're using Comparable entities, this will work on anything:
func optionalsAreEqual<T: Comparable>(firstVal: T?, secondVal: T?) -> Bool{
if let firstVal = firstVal, secondVal = secondVal {
return firstVal == secondVal
}
else{
return firstVal == nil && secondVal == nil
}
}
It's not exactly short and sweet, but it's expressive, clear, and reusable.
You can use !==
From The Swift Programming Language
Swift also provides two identity operators (
===
and!==
), which you use to test wether two objects references both refer to the same object instance.
Some good examples and explanations are also at Difference between == and ===
On @PEEJWEEJ point, doing the following will result in false
var newValue: AnyObject? = "String"
var oldValue: AnyObject? = "String"
if newValue === oldValue {
print("true")
} else {
print("false")
}
I liked @Keith's solution. But I think it is not written in Swift 4, as I can not compile it with Swift 4 compiler.
So I have converted his code to Swift 4 version here.
Remember, if you're using higher version of Swift language than Swift 4.1, then this answer is of no need as it provides this feature by default. You can refer here for more details.
Swift 4 version of @Keith's code:
infix operator ==? : ComparisonPrecedence
func ==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
if let lhs = lhs, let rhs = rhs {
return lhs == rhs
} else {
return lhs == nil && rhs == nil
}
}
func ==? <T: AnyObject>(lhs: T?, rhs: T?) -> Bool {
if let lhs = lhs, let rhs = rhs {
return lhs === rhs
} else {
return lhs == nil && rhs == nil
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With