You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Picker要求模型遵循Hashable?已实现Identifiable仍报错且ScrollView无此要求?

问题原因解析

1. Identifiable 不隐含 Hashable

你得纠正这个误解:Identifiable 协议只要求类型拥有一个唯一的 id 属性(且这个 id 必须是 Hashable 类型),但它不会自动让你的 Currency 类型本身遵循 Hashable。也就是说,Currency 满足 Identifiable 只是保证每个实例有唯一标识,但 Swift 没法直接把整个 Currency 实例当成可哈希、可对比的对象——除非你显式让它遵循 Hashable。

2. ScrollView 与 Picker 对 ForEach 的要求不同

ScrollView 场景

ScrollView 里的 ForEach 用的是专门用于视图展示的重载:

ForEach(_ data: Data, content: @escaping (Data.Element) -> Content) where Data : RandomAccessCollection, Data.Element : Identifiable

它只需要元素是 Identifiable,核心目的是通过 id 给每个子视图生成唯一标识,让 SwiftUI 能正确识别列表中需要更新的视图,不需要对比整个元素实例的相等性,自然也不需要 Hashable。

Picker 场景

Picker 是带选中状态的交互控件,核心逻辑是跟踪并匹配选中元素与列表元素。这里的 ForEach 配合 Picker 使用时,依赖两个关键要求:

  • Picker 的 selection 绑定值必须是 Hashable 类型(SwiftUI 需要用哈希值高效管理选中状态,快速查找匹配元素)
  • 列表元素类型必须和 selection 的类型一致,所以 Currency 必须遵循 Hashable,这样 Picker 才能判断“当前选中的 currentCurrency 和列表里的某个 Currency 实例是否为同一个”。

解决方法

给 Currency 类型显式添加 Hashable 协议遵循。如果你的 Currency 内的属性都是可哈希的(比如 String、Int 这类基础类型),直接在定义里加上 Hashable 即可:

struct Currency: Identifiable, Hashable {
    let id: String // 或其他Hashable类型的id
    // 其他属性...
}

如果包含自定义类型的属性,你需要手动实现 hash(into:) 方法和 == 运算符,但大部分基础场景下,Swift 会自动合成符合要求的实现。


内容的提问来源于stack exchange,提问作者LukeSideWalker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:02:48