SwiftUI中Binding值仅单次变更:按钮首次点击后其他按钮失效
问题原因与解决方案
问题根源
你的代码中Item结构体的Hashable实现存在关键问题,导致SwiftUI无法正确跟踪视图更新:
- Hash值计算不完整:
hash(into:)方法未包含id和reel属性,当reel.bid状态切换时,Item的hash值不会变化,SwiftUI的ForEach无法识别元素已更新,对应视图得不到刷新。 - 相等判断与Hash逻辑不一致:
==方法仅比较id,但hash(into:)未结合id,违反了Hashable协议的核心规则——相等的实例必须拥有相同的hash值。 - Reel未实现Hashable:
Item的hash计算依赖reel,但Reel未实现Hashable,导致无法正确计算包含reel状态变化的hash值。
修正代码
1. 让Reel实现Hashable
struct Reel: Identifiable, Hashable { var id = UUID().uuidString var player: AVPlayer var bid: Bool func hash(into hasher: inout Hasher) { hasher.combine(id) hasher.combine(bid) } static func == (lhs: Reel, rhs: Reel) -> Bool { lhs.id == rhs.id && lhs.bid == rhs.bid } }
注:AVPlayer是引用类型,这里仅比较唯一标识id和业务关心的bid状态,忽略player实例本身的差异。
2. 修正Item的Hashable实现
struct Item: Identifiable, Hashable { static func == (lhs: Item, rhs: Item) -> Bool { lhs.id == rhs.id && lhs.reel == rhs.reel } func hash(into hasher: inout Hasher) { hasher.combine(id) hasher.combine(chance) hasher.combine(name) hasher.combine(price) hasher.combine(tradeIn) hasher.combine(rarityType) hasher.combine(description) hasher.combine(reel) } var id: String = UUID().uuidString var chance: String var tradeIn: Int var name: String var price: String var rarityType: String var description: String var reel: Reel }
3. 优化TabView的Tag绑定(可选,更规范)
在ReelsView的ForEach中,使用Item自身的id作为tag,避免依赖嵌套的reel.id:
TabView(selection: $currentReel) { ForEach($items) { $item in ReelsPlayer(reel: $item.reel, currentReel: $currentReel, item: $item) .tag(item.id) } }
修复原理
当点击按钮切换item.reel.bid时,Item的hash值会因reel状态变化而更新,ForEach能正确识别元素变更并刷新对应视图,所有按钮的状态和响应逻辑就能正常工作了。
内容的提问来源于stack exchange,提问作者MaxPayne777
相关产品推荐
相关产品推荐

