SwiftUI List手动设置选中状态及增删项异常问题
解决macOS SwiftUI列表删除后详情视图不消失及新增项选中问题
问题说明
- 删除选中的列表项后,详情视图仍显示已删除项的内容,无法回到默认提示文本
- 点击ADD按钮新增列表项后,选中状态停留在原最后一项,无法自动切换到新创建的项
解决方案
1. 关联NavigationLink与selection状态
原代码中NavigationLink未与selection绑定,导致selection变化无法同步控制详情视图的显示。需修改为tag-selection绑定的形式,让selection直接控制导航状态:
NavigationLink(destination: DetailView(item: item), tag: item, selection: $selection) { Text(item) }
2. 删除时清空选中状态
在删除操作后,检查被删除的项是否为当前选中项,若是则将selection设为nil,触发详情视图关闭:
- 修改批量删除方法:
func delete(at offsets: IndexSet) { let deletedItems = offsets.map { items[$0] } items.remove(atOffsets: offsets) // 若删除的是当前选中项,清空选中状态 if deletedItems.contains(selection) { selection = nil } }
- 修复单个删除方法:
func delete(item: String) { if let index = items.firstIndex(of: item) { items.remove(at: index) // 若删除的是当前选中项,清空选中状态 if selection == item { selection = nil } } }
3. 新增项自动选中
完善add()方法确保返回正确的新项,同时因为NavigationLink已与selection绑定,设置selection = newCreatedItem即可自动选中并导航到新项详情:
func add() -> String { let newItem = "Item \(items.count + 1)" items.append(newItem) return newItem }
修改后的完整代码
struct DetailView: View { var item: String var body: some View { Text("Detail of \(item)") } } struct ContentView: View { @State private var items = ["Item 1", "Item 2", "Item 3"] @State private var selection: String? var body: some View { NavigationView { VStack { List { ForEach(items, id: \.self, selection: $selection) { item in // 修改NavigationLink为tag-selection绑定形式 NavigationLink(destination: DetailView(item: item), tag: item, selection: $selection) { Text(item) } } .onDelete(perform: delete) } Button { let newCreatedItem = add() selection = newCreatedItem // 现在可以正常触发选中和导航 } label: { Image(systemName: "add") } Button { if let item = selection { delete(item: item) } } label: { Image(systemName: "minus.rectangle.fill") } .disabled(selection == nil) } Text("Please select an item.") } } func delete(at offsets: IndexSet) { let deletedItems = offsets.map { items[$0] } items.remove(atOffsets: offsets) if deletedItems.contains(selection) { selection = nil } } func delete(item: String) { if let index = items.firstIndex(of: item) { items.remove(at: index) if selection == item { selection = nil } } } func add() -> String { let newItem = "Item \(items.count + 1)" items.append(newItem) return newItem } }
内容的提问来源于stack exchange,提问作者FaiChou
相关产品推荐
相关产品推荐

