NavigationSplitView绑定结构体失效,绑定ID正常的问题求助
你遇到的问题核心在于List的selection绑定类型与ForEach元素的匹配逻辑:
- 绑定整个
Annotation对象时,SwiftUI依赖Hashable协议实现追踪选中状态,但默认合成的Hashable会使用结构体所有属性计算哈希值,这会导致状态更新识别失效; - 绑定
Annotation.ID(UUID)时,ID是唯一且稳定的标识,SwiftUI能准确追踪选中状态的变化,因此功能正常。
方案1:修正Annotation的Hashable实现
让Hashable和Equatable仅依赖id属性(唯一标识),确保SwiftUI能正确识别选中对象:
struct ContentView: View { var notes = [ Annotation(title: "Note 1", details: "Some details here", completed: false), Annotation(title: "Note 2", details: "Some details here too", completed: true), Annotation(title: "Note 3", details: "Some details here also", completed: false) ] @State private var selected: Annotation? var body: some View { NavigationSplitView(columnVisibility: .constant(.doubleColumn)) { List (selection: $selected) { ForEach(notes) { annotation in Text(annotation.title) } } } detail: { VStack { Text(selected?.title ?? "-") Text(selected?.details ?? "-") } } } } struct Annotation: Hashable, Identifiable { var id: UUID = UUID() var title: String var details: String var completed: Bool // 自定义哈希计算,仅基于id func hash(into hasher: inout Hasher) { hasher.combine(id) } // 自定义相等判断,仅比较id static func == (lhs: Annotation, rhs: Annotation) -> Bool { lhs.id == rhs.id } }
方案2:保持绑定ID的方式(推荐)
ID是更轻量、稳定的标识,尤其适合数据来自网络/数据库的场景。只需根据ID匹配对应的对象即可:
struct ContentView: View { var notes = [ Annotation(title: "Note 1", details: "Some details here", completed: false), Annotation(title: "Note 2", details: "Some details here too", completed: true), Annotation(title: "Note 3", details: "Some details here also", completed: false) ] @State private var selectedId: Annotation.ID? // 根据ID获取选中对象 private var selectedAnnotation: Annotation? { notes.first { $0.id == selectedId } } var body: some View { NavigationSplitView(columnVisibility: .constant(.doubleColumn)) { List (selection: $selectedId) { ForEach(notes) { annotation in Text(annotation.title) } } } detail: { VStack { Text(selectedAnnotation?.title ?? "-") Text(selectedAnnotation?.details ?? "-") } } } } struct Annotation: Hashable, Identifiable { var id: UUID = UUID() var title: String var details: String var completed: Bool }
内容的提问来源于stack exchange,提问作者DeveloperSammy
相关产品推荐
相关产品推荐

