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

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")
        }
    }
}

关键说明:

  1. 每个Section的isEditing状态完全独立,切换时仅影响当前Section的List
  2. 自定义编辑按钮和系统默认EditButton()行为一致,动态显示"Edit"/"Done"文本
  3. 通过.environment(\.editMode, ...)强制List使用当前Section的编辑状态,脱离全局环境控制
  4. 保留原有onDelete回调,确保滑动删除和编辑模式下的批量删除功能正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:10:27