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

NavigationSplitView侧边栏列表中NavigationLink选中状态异常问题

macOS 14+ NavigationSplitView侧边栏List选中状态UI异常修复方案

问题原因

这是macOS 14及以后版本中SwiftUI List视图复用机制导致的UI状态不同步问题:当选中行滚出视野后,对应的List单元格会被系统复用给新行,而原选中状态的UI标记没有被正确重置,导致返回滚动时旧行仍显示选中样式,尽管selection绑定的实际值是正确的。

解决方案

方案1:自定义行选中背景,强制UI与状态同步

通过手动设置行的背景样式,覆盖系统默认的选中样式,确保UI完全跟随selection状态变化:

struct ContentView: View {
    
    @State private var selection: Int? = nil
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selection) {
                ForEach(0...60, id: \.self) { item in
                    NavigationLink("Row \(item)", value: item)
                        // 自定义选中背景,匹配系统原生样式
                        .listRowBackground(selection == item ? Color.accentColor.opacity(0.2) : Color.clear)
                }
            }
        } content: {
            Text("Selected row is \(selection ?? 0)")
        } detail: {
            Text("Selected row is \(selection ?? 0)")
        }
    }
}

方案2:给行添加动态ID,强制视图刷新

通过为每个行设置包含selection状态的动态ID,让SwiftUI在选中状态变化时重新渲染行视图,避免复用导致的状态残留:

struct ContentView: View {
    
    @State private var selection: Int? = nil
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selection) {
                ForEach(0...60, id: \.self) { item in
                    NavigationLink("Row \(item)", value: item)
                        // 动态ID包含选中状态,确保状态变化时视图刷新
                        .id("\(item)-\(selection ?? -1)")
                }
            }
        } content: {
            Text("Selected row is \(selection ?? 0)")
        } detail: {
            Text("Selected row is \(selection ?? 0)")
        }
    }
}

改用显式绑定tag和selection的NavigationLink初始化方式,强化状态与UI的绑定关系:

struct ContentView: View {
    
    @State private var selection: Int? = nil
    
    var body: some View {
        NavigationSplitView {
            List {
                ForEach(0...60, id: \.self) { item in
                    NavigationLink(
                        "Row \(item)",
                        tag: item,
                        selection: $selection
                    ) {
                        Text("Selected row is \(item)")
                    }
                }
            }
        } content: {
            Text("Selected row is \(selection ?? 0)")
        } detail: {
            Text("Selected row is \(selection ?? 0)")
        }
    }
}

以上三种方案都能解决该UI异常问题,其中方案1最贴近系统原生样式,方案2和3则从视图渲染机制层面避免了状态残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:45:56