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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 08:02:33