在开发YLLabel过程中,收到这样两个error:
Type 'YLLabelType' does not conform to protocol 'Hashable'
Type 'YLLabelType' does not conform to protocol 'Equatable'
开始不知道为什么会报这个错,后来看了一些资料,写出来,大家多多指教;
一. Hashable 哈希
一个类型为了存储在集合中,该类型必须是可哈希化的-该类型必须提供一种方法计算它的哈希值,一个哈希值为Int类型,相等的对象哈希值必须相同。
Swift的所有基本类型(形如String,Int,Double,Bool)默认是可哈希化的,可以作为集合的值的类型或者字典的键的类型。没有关联值的枚举成员值默认也是可哈希化的。(万幸的是,我用到了枚举关联值,不然我是不知道这些的)
因为要实现用户自定义高亮类型,所以YLLabelType
里提供了这样一个接口
case custom(pattern:String)
pattern 是想要匹配的规则
用户想给自定义的类型添加颜色和点击事件的时候,
提供了customColor 和 customHandler
类型是字典, type 作为 key , 颜色和点击事件作为 value
这时,就提示了上面提到的
Type 'YLLabelType' does not conform to protocol 'Hashable'
我们可以看到 协议Hashable是准守了Equatable协议,并且提供了一个需要我们实现 get 方法的属性 hashValue
public protocol Hashable : Equatable {
/// The hash value.
///
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
public var hashValue: Int { get }
}
我的实现(-3,-2,-1,随手写的,能区分就好吧???求指点)
extension YLLabelType : Hashable, Equatable{
public var hashValue : Int {
switch self {
case .hashtag : return -3
case .mention : return -2
case .URL : return -1
case .custom(let pattern) : return pattern.hashValue
}
}
}
二. Equatable 判等
在判等上 Swift 的行为和 Objective-C 有着巨大的差别。在 Objective-C 中 ==
这个符号的意思是判断两个对象是否指向同一块内存地址。其实很多时候这并不是我们经常所期望的判等,我们更关心的往往还是对象的内容相同,而这种意义的相等即使两个对象引用的不是同一块内存地址时,也是可以做到的。
因为YLLabelType
加入了case custom(pattern:String)
所以判等的时候,就需要我们遵循Equatable
public protocol Equatable {
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func ==(lhs: Self, rhs: Self) -> Bool
}
第一眼看到怪怪的,其实就是方法名是==,和普通方法一样了就
我的实现
public func == (lhs: YLLabelType, rhs: YLLabelType) -> Bool {
switch (lhs, rhs) {
case (.mention, .mention): return true
case (.hashtag, .hashtag): return true
case (.URL, .URL): return true
case (.custom(let pattern1), .custom(let pattern2)):
return pattern1 == pattern2
default: return false
}
}
还要多说一点的是
对于==
的实现我们并没有像实现其他一些协议一样将其放在对应的 extension
里,而是放在了全局,因为你应该需要在全局范围内都能使用 ==
这时候,可能会报一个错
只要在枚举定义enum前面加上public就可以了