SwiftUI 按平台限制EditButton()作用范围的实现问题
解决单个Section独立控制List编辑状态的问题
系统默认的EditButton()会修改视图树中全局共享的editMode环境变量,这就是为什么点击一个Section的编辑按钮会让所有List都进入编辑状态。要实现每个Section独立控制自己的List,需要给每个Section视图添加独立的编辑状态变量,手动控制编辑模式,而非依赖系统全局环境变量。
具体实现步骤:
- 给每个Section视图添加独立的
@State变量,用于控制当前Section的编辑状态 - 手动实现自定义编辑切换按钮,替代系统默认的
EditButton() - 将List的
editMode环境变量绑定到当前Section的独立状态上 - 保留
onDelete回调,确保编辑模式下的批量删除和非编辑模式的滑动删除都正常工作
修改后的完整代码:
struct ContentView: View { @State private var selectedItem: String? @State private var items = ["One", "Two", "Three", "Four", "Five"] @State private var fruits = ["Apple", "Orange", "Pear", "Lemon", "Grape"] var body: some View { NavigationSplitView { ItemSection(selectedItem: $selectedItem, items: $items) FruitSection(selectedItem: $selectedItem, fruits: $fruits) } detail: { if let selectedItem { ItemDetailView(selectedItem: selectedItem) } else { EmptyView() } } } } struct ItemSection: View { @Binding var selectedItem: String? @Binding var items: [String] // 独立控制当前Section的编辑状态 @State private var isEditing = false var body: some View { Section { VStack { List(selection: $selectedItem) { ForEach(items, id: \.self) { item in NavigationLink(value: item) { Text(item) } } .onDelete { items.remove(atOffsets: $0) } } .listStyle(PlainListStyle()) // 将List的编辑模式绑定到当前Section的独立状态 .environment(\.editMode, .constant(isEditing ? .active : .inactive)) } .padding() } header: { HStack { Text("Section for Items") Spacer() // 自定义编辑按钮,切换isEditing状态 Button(isEditing ? "Done" : "Edit") { isEditing.toggle() } #if targetEnvironment(macCatalyst) .buttonStyle(BorderedButtonStyle()) #endif } .padding(.horizontal, 10) } } } struct FruitSection: View { @Binding var selectedItem: String? @Binding var fruits: [String] // 独立控制当前Section的编辑状态 @State private var isEditing = false var body: some View { Section { VStack { List(selection: $selectedItem) { ForEach(fruits, id: \.self) { fruit in NavigationLink(value: fruit) { Text(fruit) } } .onDelete { fruits.remove(atOffsets: $0) } } .listStyle(PlainListStyle()) // 将List的编辑模式绑定到当前Section的独立状态 .environment(\.editMode, .constant(isEditing ? .active : .inactive)) } .padding() } header: { HStack { Text("Section for Fruits") Spacer() // 自定义编辑按钮,切换isEditing状态 Button(isEditing ? "Done" : "Edit") { isEditing.toggle() } #if targetEnvironment(macCatalyst) .buttonStyle(BorderedButtonStyle()) #endif } .padding(.horizontal, 10) } } } struct ItemDetailView: View { var selectedItem: String var body: some View { VStack { Text(selectedItem) Text("This is the DetailView") } } }
关键说明:
- 每个Section的
isEditing状态完全独立,切换时仅影响当前Section的List - 自定义编辑按钮和系统默认
EditButton()行为一致,动态显示"Edit"/"Done"文本 - 通过
.environment(\.editMode, ...)强制List使用当前Section的编辑状态,脱离全局环境控制 - 保留原有
onDelete回调,确保滑动删除和编辑模式下的批量删除功能正常
内容的提问来源于stack exchange,提问作者JohnSF
相关产品推荐
相关产品推荐

