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

Reply via email to