[swift-users] Using NSObject subclass instance as key in Dictionary

Etan Kissling kissling at oberon.ch
Thu Dec 17 16:17:43 CST 2015


I want to use instances of a custom class as Dictionary key.
This requires the class to conform to Hashable.

func ==(lhs: KeyType1, rhs: KeyType1) -> Bool { return lhs.id == rhs.id }

final class KeyType1: Hashable, CustomStringConvertible {
    let id: String
    init(id: String) { self.id = id }
    var hashValue: Int { return id.hashValue }
    var description: String { return id }
}


Now I can use KeyType1 instances as key in Dictionary.

var collection1 = [KeyType1(id: "foo") : NSObject()]


Testing works fine:

    let key = collection1.first!.0
    print("        Key stored in collection: \(unsafeAddressOf(key)) -- \(key)")



    let keyCopy = KeyType1(id: key.id)
    print("                        Key copy: \(unsafeAddressOf(keyCopy)) -- \(keyCopy)")



    print("                      Keys equal: \(key == keyCopy)")
    print("               Hash values equal: \(key.hashValue == keyCopy.hashValue)")
    print("     Collection has item for key: \(collection1[key] != nil)")
    print("Collection has item for key copy: \(collection1[keyCopy] != nil)")

        Key stored in collection: 0x0000608000043d80 -- foo
                        Key copy: 0x00006080000440b0 -- foo
                      Keys equal: true
               Hash values equal: true
     Collection has item for key: true
Collection has item for key copy: true



Next, I repeat the same set up -- but this time KeyType is a descendant of NSObject.

func ==(lhs: KeyType2, rhs: KeyType2) -> Bool { return lhs.id == rhs.id }

final class KeyType2: NSObject { // NSObject conforms to Hashable and CustomStringConvertible.
    let id: String
    init(id: String) { self.id = id; super.init() }
    override var hashValue: Int { return id.hashValue }
    override var description: String { return id }
}

Again, I create a Dictionary based on this key class.

var collection2 = [KeyType2(id: "foo") : NSObject()]

Using the same tests, they fail now.

    let key = collection2.first!.0
    print("        Key stored in collection: \(unsafeAddressOf(key)) -- \(key)")

    let keyCopy = KeyType2(id: key.id)
    print("                        Key copy: \(unsafeAddressOf(keyCopy)) -- \(keyCopy)")

    print("                      Keys equal: \(key == keyCopy)")
    print("               Hash values equal: \(key.hashValue == keyCopy.hashValue)")
    print("     Collection has item for key: \(collection2[key] != nil)")
    print("Collection has item for key copy: \(collection2[keyCopy] != nil)")

        Key stored in collection: 0x0000608000044080 -- foo
                        Key copy: 0x00006080000440e0 -- foo
                      Keys equal: true
               Hash values equal: true
     Collection has item for key: true
Collection has item for key copy: false


What am I missing here?


Thanks

Etan






-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20151217/356ace5e/attachment.html>


More information about the swift-users mailing list