gpt4 book ai didi

ios - 使 swift 协议(protocol)符合 Hashable

转载 作者:行者123 更新时间:2023-12-04 12:00:21 25 4
gpt4 key购买 nike

我绕着圈子试图得到 Hashable使用多个 struct符合相同protocol .
我有一个协议(protocol) SomeLocation声明如下:

protocol SomeLocation {
var name:String { get }
var coordinates:Coordinate { get }
}
然后我创建多个包含类似数据的对象,如下所示:
struct ShopLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate

init(from decoder: Decoder) throws {
...
}
}

struct CarLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate

init(from decoder: Decoder) throws {
...
}
}
我稍后可以通过声明在同一个数组中使用它们:
let locations: [SomeLocation]
问题是,我创建了一个 MKAnnotation子类,需要使用自定义 HashableSomeLocation对象。
final class LocationAnnotation:NSObject, MKAnnotation {
let location:SomeLocation
init(location:SomeLocation) {
self.location = location
super.init()
}
}

override var hash: Int {
return location.hashValue
}

override func isEqual(_ object: Any?) -> Bool {
if let annot = object as? LocationAnnotation
{
let isEqual = (annot.location == location)
return isEqual
}
return false
}
这给了我2个错误:

Value of type 'SomeLocation' has no member 'hashValue' Binary operator

'==' cannot be applied to two 'SomeLocation' operands


所以我添加了 Hashable我的 SomeLocation 的协议(protocol)协议(protocol):
protocol SomeLocation: Hashable {
...
}
这消除了 hashValue 不可用的第一个错误,但现在我在声明 let location:SomeLocation 的地方得到一个错误说

Protocol 'SomeLocation' can only be used as a generic constraint because it has Self or associated type requirements


所以看起来我不能添加 Hashable到协议(protocol)。
我可以添加 Hashable直接到实现 SomeLocation 的每个结构协议(protocol),但这意味着我需要使用这样的代码,并在每次创建另一个符合 SomeLocation 的对象时不断更新它。协议(protocol)。
override var hash: Int {
if let location = location as? ShopLocation
{
return location.hashValue
}
return self.hashValue
}
我尝试了另一种方法,通过制作 SomeLocationRepresentable结构:
struct SomeLocationRepresentable {
private let wrapped: SomeLocation
init<T:SomeLocation>(with:T) {
wrapped = with
}
}
extension SomeLocationRepresentable: SomeLocation, Hashable {
var name: String {
wrapped.name
}

var coordinates: Coordinate {
wrapped.coordinates
}

func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(coordinates)
}

static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name && lhs.coordinates == rhs.coordinates
}
}
但是,当我尝试在 LocationAnnotation 中使用它时类
let location: SomeLocationRepresentable
init(location:SomeLocation) {
self.location = SomeLocationRepresentable(with: location)
super.init()
}
我收到一个错误

Value of protocol type 'SomeLocation' cannot conform to 'SomeLocation'; only struct/enum/class types can conform to protocols


是否有可能实现我想要做的事情?使用所有符合协议(protocol)的对象并使用自定义 Hashable比较一个?

最佳答案

Hashable 导出协议(protocol)并使用类型橡皮擦可能会有所帮助:

protocol SomeLocation: Hashable {
var name: String { get }
var coordinates: Coordinate { get }
}

struct AnyLocation: SomeLocation {
let name: String
let coordinates: Coordinate

init<L: SomeLocation>(_ location: L) {
name = location.name
coordinates = location.coordinates
}
}
然后,您可以简单地声明结构上的协议(protocol)一致性,如果 Coordinate已经是 Hashable , 那么你不需要编写任何额外的哈希代码代码,因为编译器可以自动为你合成(只要它们的所有属性都是 Hashable ,新类型也会这样做:
struct ShopLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
}

struct CarLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
}
如果 Coordinate也是 Codable ,那么您也可以省略编写任何编码/解码操作的代码,编译将合成所需的方法(假设所有其他属性都已经 Codable )。
然后,您可以通过转发初始化器约束在注释类中使用橡皮擦:
final class LocationAnnotation: NSObject, MKAnnotation {   
let location: AnyLocation

init<L: SomeLocation>(location: L) {
self.location = AnyLocation(location)
super.init()
}

override var hash: Int {
location.hashValue
}

override func isEqual(_ object: Any?) -> Bool {
(object as? LocationAnnotation)?.location == location
}
}

关于ios - 使 swift 协议(protocol)符合 Hashable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64468530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com