Turns out that for `NSObject`, protocol `Equatable` wasn't used. Instead, it used `NSObjectProtocol.isEqual(_ object: Any?)`. Also, override `func isEqual(_ object: Any?) -> Bool` requires to override `var hash: Int { get }` as well.
I think this behavior should be mentioned in Swift docs or manual in `Set` section. Below code works. class Bar:NSObject { let value:Int override public var hashValue: Int { return value } public static func ==(lhs: Bar, rhs: Bar) -> Bool { return lhs.value == rhs.value } // required by NSObjectProtocol override func isEqual(_ object: Any?) -> Bool { if let rhs = object as? Bar { return self == rhs } return false } override var hash: Int { return self.hashValue } init(_ value:Int) { self.value = value } } let barSetA:Set = [Bar(8), Bar(9)] let barSetB:Set = [Bar(9), Bar(10)] let barResultC = barSetA.intersection(barSetB) // {{NSObject, value 9}} let barResultD = barSetA.subtracting(barSetB) // {{NSObject, value 8}} Gladly I find it here <http://stackoverflow.com/questions/32726524/swift-2-0-set-not-working-as-expected-when-containing-nsobject-subclass> . Zhaoxin On Wed, Mar 29, 2017 at 3:50 AM, Zhao Xin <owe...@gmail.com> wrote: > Please see the code first. > > import Foundation > > > class Foo:Hashable { > > let value:Int > > > > public var hashValue: Int { return value } > > public static func ==(lhs: Foo, rhs: Foo) -> Bool { > > return lhs.value == rhs.value > > } > > > > init(_ value:Int) { > > self.value = value > > } > > } > > > let fooSetA:Set = [Foo(8), Foo(9)] > > let fooSetB:Set = [Foo(9), Foo(10)] > > let fooResultC = fooSetA.intersection(fooSetB) // {{value 9}} > > let fooResultD = fooSetA.subtracting(fooSetB) // {{value 8}} > > > > class Bar:NSObject { > > let value:Int > > > > override public var hashValue: Int { return value } > > public static func ==(lhs: Bar, rhs: Bar) -> Bool { > > return lhs.value == rhs.value > > } > > > > init(_ value:Int) { > > self.value = value > > } > > } > > > let barSetA:Set = [Bar(8), Bar(9)] > > let barSetB:Set = [Bar(9), Bar(10)] > > let barResultC = barSetA.intersection(barSetB) // Set([]) > > let barResultD = barSetA.subtracting(barSetB) // {{NSObject, value 9}, > {NSObject, value 8}} > > > Behaviors of `func intersection(Set<Set.Element>)` and `func > subtracting(Set<Set.Element>)` were different between normal Swift class > and NSObject subclasses. I had thought they should be the same. It seemed > that Set<NSObject> relied on addresses of NSObject instances instead of > their hashValues. That made the Set useless. > > Swift version: 3.1 (swiftlang-802.0.48 clang-802.0.48) > Xcode 8.3 (8E162) > > Zhaoxin > > > > > > > > > > >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users