Overridden == function for Equatable type not called for custom class that subclasses NSCoding and NSObject
Solution 1
Because your class inherits from NSObject
you do not need to use the swift protocol Equatable
instead you must override the NSObject
method isEquals
:
Swift 3.x and above
class FooBar: NSObject, NSCoding {
override func isEqual(_ object: Any?) -> Bool {
return id == (object as? FooBar)?.id
}
}
(Thanks to Kamchatka)
Swift 2.x
class FooBar: NSObject, NSCoding {
override func isEqual(object: AnyObject?) -> Bool {
return id == (object as? FooBar)?.id
}
}
Solution 2
You are getting this error because NSObject already conforms to Equatable through its isEqual method.
So I'm not sure if this is the correct way of doing this, but you could override the isEqual method of NSObject:
class FooBar: NSObject, NSCoding {
...
override func isEqual(object: AnyObject?) -> Bool {
return self == (object as? FooBar)
}
Crashalot
Hello. My friends call me SegFault. Describe myself in 10 seconds? You know those feisty, whip-smart, sometimes funny, and occasionally charming developers who dominate StackOverflow and consider Swift/Ruby/jQuery their native tongue? Yah, I buy coffee for them.
Updated on June 14, 2022Comments
-
Crashalot about 2 years
The
FooBar
class below has to override the==
function of theEquatable
type.However, calling
contains
on an array ofFooBar
objects does not cause a breakpoint inside the custom==
function to get invoked. Is it possible another==
function is overriding this custom one?Note: Because FooBar must subclass from NSCoding and NSObject, FooBar does not list Equatable as a protocol because it causes this error:
Redundant conformance of 'FooBar' to protocol 'Equatable'
func ==(lhs: FooBar, rhs: FooBar) -> Bool { return lhs.id == rhs.id } class FooBar: NSObject, NSCoding { // Class def } // Both serverFooBars and gFooBars are [FooBar] let newFooBars = serverFooBars.filter { !gFooBars.contains($0) }
-
Crashalot about 8 yearsDoing so caused an error, hence its omission. The error: Redundant conformance of 'Recipe' to protocol 'Equatable'
-
Blake Lockley about 8 years@Crashalot is it required your class inherits from NSObject for any reason?
-
Crashalot about 8 yearsIsn't it needed for NSCoding?
-
Daniel Krom about 8 yearslook at the Equatable protocol, you must implement:
func ==(lhs: Self, rhs: Self) -> Bool
(inside the class) -
Blake Lockley about 8 years@Crashalot thats correct, the reason its saying its redundant because the class inherits from NSObject has the
isEquals
method.. though im going to check this out myself now -
Blake Lockley about 8 years@DanielKrom, i mention that must be implemented in my answer but i will edit it to make it more clear
-
Crashalot about 8 years@DanielKrom inside the class generates an error; you're sure?
-
Crashalot about 8 years@BlakeLockley yes the question is how to override == if you must also subclass NSCoding?
-
Daniel Krom about 8 years@Crashalot yep nshipster.com/swift-comparison-protocols
-
Blake Lockley about 8 years@DanielKrom my bad i mis read your comment, no it must be implemented outside of the class because when you use the equatable function you are not within the scope of the class. e.g. fooBar == fooBar is not the same as calling a method on fooBar.
-
Blake Lockley about 8 years@Crashalot override isEquals - ill edit my answer
-
Daniel Krom about 8 years@BlakeLockley Hmm, The syntax is like global operator, but if you implement a protocol you have to implement the protocol functions inside the class that implements that, but I may be wrong
-
Crashalot about 8 yearsCool will try and report back!
-
Blake Lockley about 8 years@DanielKrom thats true for all protocols with the exceptions being
Equatable
andComparable
or any other protocol that requires an overload implementation of an operator. -
Crashalot about 8 yearsThat worked but unfortunately Blake was helping earlier and published his answer a bit sooner. Thanks though!
-
Crashalot about 8 yearsWorks thanks so much! Would be ideal if you included the
self == (object as? FooBar) bit
from Odrakir's answer as this is even more explicit for Swift newbies. -
Odrakir about 8 yearsI see that now. He didn't show how to still use the == override, though... :)
-
Blake Lockley about 8 years@Crashalot ill share the love and upvote this one aswell, glad we all could help!
-
Blake Lockley about 8 years@Crashalot no worries :) you could just include your implementation of
==
inside theisEquals
then theres no reason to downcast it and call==
. But thats all down to preference. -
Crashalot about 8 yearsHe updated the answer to show how to use the == override. It's true your answer is more explicit, but you can see how much time Blake spent beforehand and he gave the right answer -- just not the perfect answer like yours. Your answer was upvoted, though! :)
-
Crashalot about 8 yearsHow do you not downcast it?
-
Odrakir about 8 yearsCan't see the part about overriding ==, but, ok, whatever...
-
Blake Lockley about 8 years@Crashalot i'll edit my answer
-
Blake Lockley about 8 years@Crashalot my mistake, you still need to perform a downcast for the other object but this way you dont need to worry about implementation of
==
. -
Kamchatka over 7 yearsNote: In Swift 3 the signature of this method is now:
override func isEqual(_ object: Any?) -> Bool {