Overridden == function for Equatable type not called for custom class that subclasses NSCoding and NSObject [duplicate]
Asked Answered
F

2

30

The FooBar class below has to override the == function of the Equatable type.

However, calling contains on an array of FooBar 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) }
Fond answered 7/5, 2016 at 7:34 Comment(0)
C
61

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
  }
}
Collegiate answered 7/5, 2016 at 7:39 Comment(20)
Doing so caused an error, hence its omission. The error: Redundant conformance of 'Recipe' to protocol 'Equatable'Fond
@Fond is it required your class inherits from NSObject for any reason?Collegiate
Isn't it needed for NSCoding?Fond
look at the Equatable protocol, you must implement: func ==(lhs: Self, rhs: Self) -> Bool (inside the class)Whitish
@Fond 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 nowCollegiate
@DanielKrom, i mention that must be implemented in my answer but i will edit it to make it more clearCollegiate
@DanielKrom inside the class generates an error; you're sure?Fond
@BlakeLockley yes the question is how to override == if you must also subclass NSCoding?Fond
@Fond yep nshipster.com/swift-comparison-protocolsWhitish
@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.Collegiate
@Fond override isEquals - ill edit my answerCollegiate
@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 wrongWhitish
Cool will try and report back!Fond
@DanielKrom thats true for all protocols with the exceptions being Equatable and Comparable or any other protocol that requires an overload implementation of an operator.Collegiate
Works 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.Fond
@Fond no worries :) you could just include your implementation of == inside the isEquals then theres no reason to downcast it and call ==. But thats all down to preference.Collegiate
How do you not downcast it?Fond
@Fond i'll edit my answerCollegiate
@Fond my mistake, you still need to perform a downcast for the other object but this way you dont need to worry about implementation of == .Collegiate
Note: In Swift 3 the signature of this method is now: override func isEqual(_ object: Any?) -> Bool {Giff
H
4

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)
}
Habituate answered 7/5, 2016 at 7:52 Comment(5)
That worked but unfortunately Blake was helping earlier and published his answer a bit sooner. Thanks though!Fond
I see that now. He didn't show how to still use the == override, though... :)Habituate
@Fond ill share the love and upvote this one aswell, glad we all could help!Collegiate
He 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! :)Fond
Can't see the part about overriding ==, but, ok, whatever...Habituate

© 2022 - 2024 — McMap. All rights reserved.