NSObject’s hash (which Set uses) is done via ObjectIdentifier, which IIRC uses something along the lines of the object's address. That’s why you’re getting the behavior you’re seeing.
Saagar Jha > On Mar 28, 2017, at 20:20, Zhao Xin via swift-users <swift-users@swift.org> > wrote: > > 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 > <mailto: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
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users