Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom equality in swift objects preserving compatibility with legacy Objective-C code

Tags:

equality

swift

In Objective-C you would do something along the lines of

- (BOOL)isEqual:(id)other {     if (other == self)         return YES;     if (!other || ![other isKindOfClass:[self class]])         return NO;     return [self.customProperty isEqual:other.customProperty]; } 

My first naive attempt in swift goes as follows

func isEqual(other: AnyObject) -> Boolean {     if self === other {         return true     }     if let otherTyped = other as? MyType {         return self.myProperty == otherTyper.myProperty     }     return false } 

But I'm far from being happy with it. I don't even know whether the signature is right or whether we're supposed to use anything different than isEqual.

Any thoughts?

EDIT: I'd also like to keep Objective-C compatibility (my class is used in both legacy Obj-C code and new Swift code). So I think only overriding == isn't enough. Am I wrong?

like image 474
Gabriele Petronella Avatar asked Jun 03 '14 18:06

Gabriele Petronella


2 Answers

Yes, you need to override isEqual (and hash) to make your objects fully Objective-C compatible. Here's a Playground-ready example for the syntax:

import Foundation  class MyClass: NSObject {      var value = 5      override func isEqual(object: AnyObject?) -> Bool {         if let object = object as? MyClass {             return value == object.value         } else {             return false         }     }      override var hash: Int {         return value.hashValue     } }  var x = MyClass() var y = MyClass() var set = NSMutableSet()  x.value = 10 y.value = 10 set.addObject(x)  x.isEqual(y) // true set.containsObject(y) // true 

(syntax current as of Xcode 6.3)

like image 160
nschum Avatar answered Sep 21 '22 18:09

nschum


You could also implement a custom equatable, for instance:

func == (lhs: CustomClass, rhs: CustomClass) -> Bool {      return lhs.variable == rhs.variable } 

This will allow you to simply check equality like this:

let c1: CustomClass = CustomClass(5) let c2: CustomClass = CustomClass(5)  if c1 == c2 {      // do whatever } 

Be sure your custom equatable is outside the class scope!

like image 39
Gregg Avatar answered Sep 24 '22 18:09

Gregg