子类化MKAnnotation原因集集合不起作用

时间:2018-11-12 18:44:36

标签: ios swift inheritance set mapkit

我刚刚发现Set类型的MKAnnotation无法正常工作。

class MyAnnotation: MKPointAnnotation {
    let id: String

    init(_ id: String) {
        self.id = id
    }

    override var hash: Int {
        return id.hash
    }

    static func ==(lhs: MyAnnotation, rhs: MyAnnotation) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
}

let m1 = MyAnnotation("1")
let m2 = MyAnnotation("2")
let n1 = MyAnnotation("1")
let n2 = MyAnnotation("2")

m1.hashValue //918
n1.hashValue //918

m2.hashValue //921
n2.hashValue //921

if m1 == n1 && m2 == n2 {
    print(true)
}
// prints true

let s1 = Set(arrayLiteral: m1, m2)
let s2 = Set(arrayLiteral: n1, n2)

let i = s1.intersection(s2)
// empty

即使散列相同,m和n的交集也是空的。请与下面的示例进行比较:

class MyAnnotation: Hashable, Equatable {
    let id: String

    init(_ id: String) {
        self.id = id
    }

    var hashValue: Int {
        return id.hash
   }

    static func ==(lhs: MyAnnotation, rhs: MyAnnotation) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
}

let m1 = MyAnnotation("1")
let m2 = MyAnnotation("2")
let n1 = MyAnnotation("1")
let n2 = MyAnnotation("2")

m1.hashValue //918
n1.hashValue //918

m2.hashValue //921
n2.hashValue //921

if m1 == n1 && m2 == n2 {
    print(true)
}
// prints true

let s1 = Set(arrayLiteral: m1, m2)
let s2 = Set(arrayLiteral: n1, n2)

let i = s1.intersection(s2)
// {{id "1"}, {id "2"}}

m和n的交集符合预期。

这很奇怪吗?也许中间有些东西我不知道也不了解。

Xcode 10.1

2 个答案:

答案 0 :(得分:0)

在第一个代码中,您没有使用Equatable协议,但是在第二个代码中,您使用了Equatable协议,因此它可以正常工作。

使用quaquatable协议进行比较。您可以参考下面的链接以获取更多信息:

https://useyourloaf.com/blog/swift-equatable-and-comparable/

答案 1 :(得分:0)

解决方案是覆盖isEqual(_ object: Any?) -> Bool

由于MKAnnotation源自NSObject,因此我们需要覆盖NS的方法。如果我们深入研究实现(^ + ),我们会发现:

  

NSObject的子类可以通过覆盖isEqual(_:)来定制Equatable一致性。如果两个对象相等,则它们必须具有相同的哈希值,因此,如果覆盖isEqual(_:),请确保还覆盖hash属性。