Compare Two Nsobject in Swift

compare two NSObject in Swift

NSObject has a method named isEqual(object:) that is used for comparing different objects. The default implementation just compares instance pointers, but subclasses can override this method to do custom comparisons.

For example:

class Foo : NSObject {
var number = 0

override func isEqual(object: AnyObject?) -> Bool {

if let otherFoo = object as? Foo {
return self.number == otherFoo.number
}
return false
}
}

Swift's == operatior automatically uses the isEqual(object:) method when comparing NSObject instances.

let foo1 = Foo()
let foo2 = Foo()
print("Equal: \(foo1 == foo2)") // true

foo1.number = 1
foo2.number = 2
print("Equal: \(foo1 == foo2)") // false

let anotherObject = NSObject()
print("Equal: \(foo1 == anotherObject)") // false

How to override NSObject's default comparison in Swift

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

How to compare Any value types

The only way to do this is with a function other than == that takes a type parameter, and then compares the values if they are both of that type:

func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool {
guard let a = a as? T, let b = b as? T else { return false }

return a == b
}

Now, using your variables above, you can compare them like this:

var any1: Any = 1
var any2: Any = 1

var any3: Any = "test"
var any4: Any = "test"

isEqual(type: Int.self, a: any1, b: any2) // true
isEqual(type: Int.self, a: any2, b: any3) // false
isEqual(type: String.self, a: any3, b: any4) // true

Compare two objects in Swift

You want Comparable, not Equatable. Equatable only has ==.



Related Topics



Leave a reply



Submit