Equatable NSObject With Swift 2
Subtle differences in implementing
Equatable protocol for
NSObject subclasses in Swift 1.2 and 2.0.
The best way to read this post is in Xcode playground, so go ahead and Download Playground
Instances of the type that conform to
Equatable protocol can be compared for value equality using operators
Equatable, only the
== operator is required to be
implemented. The standard library provides an implementation for
This was pretty much a copy-paste from documentation. Let’s try it in practice.
If you just have a simple struct, you will not be able to compare two instances of it.
Uncomment next line to see the following error:
Error: Binary operator
==cannot be applied to two CardStruct operands
To fix it, make sure that your structure conforms to
Equatable protocol first.
== operator as prescribed by
Now two instances of
EquatableCardStruct are equal if they have the same rank.
Since collection types are equatable by default, you can equate two arrays of
EquatableCardStructs as well with no additional effort.
So it all works well for structs, but what if you are dealing with
NSObject subclass? Let’s declare one to start with.
Now pay close attention to next line.
With Swift 1.2 (Xcode 6.3.2) it will work fine, uncomment and see for yourself.
With Swift 2.0 (Xcode 7) it will produce a compiler error.
Error: Redundant conformance of ‘CardObject’ to protocol ‘Equatable’
Usual implementation for
Now let’s try to equate some objects.
Look at the next two lines while using Swift 1.2. Notice that commenting and uncommenting line
93 doesn’t change the behavior. Despite the fact that
CardObject is not declared to conform to
Equatable, the code still works. Most likely this is due to the fact that all code is in one playground, this
== operator would most definitely fail if it were in another file.
This is where we can verify previous statement. Again, toggle comments on line
93 to see how result of the next
CardObject is conforming to
Equatable explicitly equating collections works as expected, otherwise it doesn’t, most likely
isEqual: method of
NSObject is used, which compares object hashes.
But give it a try with Swift 2.0 now. First of all you will be told that
NSObject already conforms to
Equatable, so line
93 has redundand conformance. Once you comment that line
cardObjects2 are not equal any more, because it’s all back to comparing hash values now.
In order to fix this problem, you will have to override
This class is almost identical to
CardObject, except for the
isEqual method. Another difference is that there’s no global
== implemented to compare 2 instances of
Nevertheless the comparison works.
And not just for single values, but for arrays as well.
This sure looks like a breaking change from 1.2 to 2.0. I wonder if that’s intentional or not. It does look strange that writing implementation of
== operator doesn’t actually change anything, in fact, it is never even called for
NSObject subclasses, but then the whole conformance to
Equatable is broken.
blog comments powered by Disqus