SwiftUI 如何在 EditMode 更改时执行操作?

SwiftUI how to perform action when EditMode changes?

我想在 EditMode 更改时执行操作。

具体来说,在编辑模式下,用户可以select删除一些项目。他通常会在之后按下垃圾桶按钮。但他也可以按“完成”。当他稍后再次按“编辑”时,之前 selected 的项目仍然 selected。我想清除所有项目。

struct ContentView: View {
    @State var isEditMode: EditMode = .inactive
    @State var selection = Set<UUID>()
    var items = [Item(), Item(), Item(), Item(), Item()]

    var body: some View {
        NavigationView {
            List(selection: $selection) {
                ForEach(items) { item in
                    Text(item.title)
                }
            }
            .navigationBarTitle(Text("Demo"))
            .navigationBarItems(
                leading: EditButton(),
                trailing: addDelButton
            )
            .environment(\.editMode, self.$isEditMode)
        }
    }

    private var addDelButton: some View {
        if isEditMode == .inactive {
            return Button(action: reset) {
                Image(systemName: "plus")
            }
        } else {
            return Button(action: reset) {
                Image(systemName: "trash")
            }
        }
    }

    private func reset() {
        selection = Set<UUID>()
    }
}

项目定义:

struct Item: Identifiable {
    let id = UUID()
    let title: String

    static var i = 0
    init() {
        self.title = "\(Item.i)"
        Item.i += 1
    }
}

更新 iOS 15.

此解法一石二鸟:

  1. 当 editMode 为 toggle 时,整个视图会自行重绘
  2. 可以在 editModeactivation/inactivation 上执行特定操作

希望这对其他人有帮助。

struct ContentView: View {
    @State var editMode: EditMode = .inactive
    @State var selection = Set<UUID>()
    @State var items = [Item(), Item(), Item()]

    var body: some View {
        NavigationView {
            List(selection: $selection) {
                ForEach(items) { item in
                    Text(item.title)
                }
            }
            .navigationTitle(Text("Demo"))
            .environment(\.editMode, self.$editMode)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    editButton
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    addDelButton
                }
            }
        }
    }

    private var editButton: some View {
        Button(action: {
            self.editMode.toggle()
            self.selection = Set<UUID>()
        }) {
            Text(self.editMode.title)
        }
    }

    private var addDelButton: some View {
        if editMode == .inactive {
            return Button(action: addItem) {
                Image(systemName: "plus")
            }
        } else {
            return Button(action: deleteItems) {
                Image(systemName: "trash")
            }
        }
    }
    
    private func addItem() {
        items.append(Item())
    }
    
    private func deleteItems() {
        for id in selection {
            if let index = items.lastIndex(where: { [=10=].id == id }) {
                items.remove(at: index)
            }
        }
        selection = Set<UUID>()
    }
}
extension EditMode {
    var title: String {
        self == .active ? "Done" : "Edit"
    }
    
    mutating func toggle() {
        self = self == .active ? .inactive : .active
    }
}