[swift-users] Set with element of NSObject subclasses didn't work as expected

Zhao Xin owenzx at gmail.com
Tue Mar 28 22:20:41 CDT 2017


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 <owenzx at 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
>
>
>
>
>
>
>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170329/3aa444c1/attachment.html>


More information about the swift-users mailing list