daspianist daspianist - 27 days ago 6
iOS Question

How to override NSObject's default comparison in Swift

I have a custom class

that conforms to
NSObject, NSCoding
. A
object is instantiated with a
id: String!

One of the issues I am encountering is when I perform an operation like the following:

let listOfPlayers = [Player]()
//populate listOfPlayers
if listOfPlayers.contains(aPlayer) ...

Specifically, the
would return results based on the memory pointer, and not based on the
value. As such, I would get a
in some cases and
in others.

I would like to override the default comparison methods, and did the following:

func isEqual(object: AnyObject?) -> Bool {
if let otherPlayer = object as? Player {
return self.id == otherPlayer.id
return false

static func == (lhs: Player, rhs: Player) -> Bool {
return lhs.id == rhs.id

However, these functions are not being executed. I have also tried to add
, but it returns an error "Method does not override any method from its superclass`

What is the right way to have a customer comparator so it is only comparing the


Answer Source

As of Swift 3, the isEqual method of NSObject takes an Any? parameter, so you are not overriding the correct method, that's why it is never called.

You should also override var hash: Int (equal objects must have the same hash) – otherwise the object will behave wrongly in hashable collections (sets, dictionaries):

class Player: NSObject {
    let id: String

    init(id: String) { self.id = id }

    override func isEqual(_ object: Any?) -> Bool {
        if let other = object as? Player {
            return self.id == other.id
        } else {
            return false

    override var hash: Int {
        return id.hashValue

Some tests:

let p1 = Player(id: "a")
let p2 = Player(id: "a")

print(p1 == p2) // true
print(p1 != p2) // false

// Native Swift set:
let set = Set([Player(id: "x"), Player(id: "y"), Player(id: "z")])
print(set.contains(Player(id: "y"))) // true

// Foundation set:
let nsset = NSSet(objects: Player(id: "x"), Player(id: "y"), Player(id: "z"))
print(nsset.contains(Player(id: "y"))) // true