【问题标题】:Stored property type 'CGPoint' does not conform to protocol 'Hashable',存储的属性类型“CGPoint”不符合协议“Hashable”,
【发布时间】:2021-06-14 17:22:58
【问题描述】:

想象一个卡片板。所有卡片都在我称之为 CardBoard 的视图上。

所有卡片都在一个数组中:

var cards:[Card]

每张卡片都有自己的位置。

这是卡片

struct Card: View {
  let id = UUID()
  
  var name:String
  var code:String
  var filename:String
  var position = CGPoint(x: 200, y: 250)
  
  
  init(name:String, code:String, filename:String) {
    self.name = name
    self.code = code
    self.filename = filename
  }
  
  
  var body: some View {
    Image(filename)
      .position(position)
  }
}

现在我想在屏幕上绘制它们。

var body: some View {
  ZStack {
    ForEach(cards, id:\.self) {card in
       
    }
  }
}

当我尝试这个时,Xcode 会告诉我

Generic struct 'ForEach' requires that 'Card' conform to 'Hashable'

当我将Hashable 添加到Card

struct Card: View, Hashable {

1. Stored property type 'CGPoint' does not conform to protocol 'Hashable', preventing synthesized conformance of 'Card' to 'Hashable'

有什么想法吗?

【问题讨论】:

  • 您需要向CGPoint 添加一个扩展名以使其可散列。
  • @Alexander 或者直接在Card 上实现Hashable
  • 符合func hash(into hasher: inout Hasher) { }
  • @Sulthan:这可能是更好的解决方案。据我从forums.swift.org/t/retroactive-conformances-vs-swift-in-the-os/… 了解到,将标准库类型的一致性添加到标准库协议追溯性地有一些微妙的问题。

标签: swift swiftui hashable


【解决方案1】:

谢谢大家,但是因为不方便发布链接作为解决方案,所以我在这里发布:

解决方案是使视图 Hashable 并添加:

extension CGPoint : Hashable {
  public func hash(into hasher: inout Hasher) {
    hasher.combine(x)
    hasher.combine(y)
  }
}

【讨论】:

    【解决方案2】:

    有很多类型需要相同的处理(通常称为 2 元组)。例如

    extension CGPoint: HashableSynthesizable { }
    extension CLLocationCoordinate2D: HashableSynthesizable { }
    extension MKCoordinateRegion: HashableSynthesizable { }
    extension MKCoordinateSpan: HashableSynthesizable { }
    
    /// A type whose `Hashable` conformance could be auto-synthesized,
    /// but either the API provider forgot, or more likely,
    /// the API is written in Objective-C, and hasn't been modernized.
    public protocol HashableSynthesizable: Hashable { }
    
    public extension HashableSynthesizable {
      static func == (hashable0: Self, hashable1: Self) -> Bool {
        zip(hashable0.hashables, hashable1.hashables).allSatisfy(==)
      }
    
      func hash(into hasher: inout Hasher) {
        hashables.forEach { hasher.combine($0) }
      }
    }
    
    private extension HashableSynthesizable {
      var hashables: [AnyHashable] {
        Mirror(reflecting: self).children
          .compactMap { $0.value as? AnyHashable }
      }
    }
    

    【讨论】:

      【解决方案3】:

      问题是您的Cardpoint 无法自动合成,因为它是CGPoint。您是否尝试过扩展CGPoint 以符合Hashable

      这是一个关于为CGPoint 创建哈希逻辑的非常有用的讨论:https://codereview.stackexchange.com/questions/148763/extending-cgpoint-to-conform-to-hashable

      【讨论】:

      • 请注意,接受的答案非常过时。使用链接问题中的第二个答案。
      • 接受的答案提供了 Swift 4 后实施的更新。当我第一次遇到同样的问题时,我个人觉得讨论很有趣。但是,是的,很好地指出第二个答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 2017-07-11
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多