首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI如何在EditMode更改时执行操作?

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

Stack Overflow用户
提问于 2019-09-04 08:53:21
回答 3查看 6.6K关注 0票数 11

当EditMode发生变化时,我想执行一个操作。

具体来说,在编辑模式下,用户可以选择要删除的一些项。他通常会在事后按下垃圾按钮。但他也可以按下完成。当他稍后再次按“编辑”时,以前选择的项目仍然被选中。我希望所有的物品都能清空。

代码语言:javascript
复制
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>()
    }
}

项目的定义:

代码语言:javascript
复制
struct Item: Identifiable {
    let id = UUID()
    let title: String

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

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-09-05 20:03:37

更新为iOS 15.

这个解决方案一举两得:

  1. 当editMode正在切换时,整个视图重新绘制自己。
  2. 当editMode激活/失活时,可以执行特定的操作。

希望这能帮到别人。

代码语言:javascript
复制
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: { $0.id == id }) {
                items.remove(at: index)
            }
        }
        selection = Set<UUID>()
    }
}
代码语言:javascript
复制
extension EditMode {
    var title: String {
        self == .active ? "Done" : "Edit"
    }
    
    mutating func toggle() {
        self = self == .active ? .inactive : .active
    }
}
票数 19
EN

Stack Overflow用户

发布于 2022-08-07 05:18:40

当用户退出List时,我一直在尝试清除editMode选择。对我来说,最干净的方式是对editMode的改变做出反应

确保引用@Environment变量:

代码语言:javascript
复制
@Environment(\.editMode) var editMode

在视图中添加计算属性以监视状态:

代码语言:javascript
复制
private var isEditing: Bool {
  if editMode?.wrappedValue.isEditing == true {
     return true
   }
   return false
}

然后使用.onChange(of:perform:)方法:

代码语言:javascript
复制
.onChange(of: self.isEditing) { value in
  if value == false {
    // do something
  } else {
    // something else
  }
}

合在一起:

代码语言:javascript
复制
struct ContentView: View {
  
  @Environment(\.editMode) var editMode
  @State private var selections: [String] = []
  @State private var colors: ["Red", "Yellow", "Blue"]

  private var isEditing: Bool {
    if editMode?.wrappedValue.isEditing == true {
       return true
     }
     return false
  }
  
  var body: some View {

    List(selection: $selections) {
      ForEach(colors, id: \.self) { color in
        Text("Color")
      }
    }
    .toolbar {
      ToolbarItem(placement: .navigationBarTrailing) {
        EditButton()
      }
    }
    .onChange(of: isEditing) { value in
      if value == false {
        selection.removeAll()
      }
    }
  }

}
票数 4
EN

Stack Overflow用户

发布于 2022-06-10 07:19:43

如果有人想要使用SwiftUI的EditButton()而不是自定义的Button,并且仍然想要perform action when isEditing status changes

您可以使用View extension

代码语言:javascript
复制
extension View {
    func onChangeEditMode(editMode: EditMode?, perform: @escaping (EditMode?)->()) -> some View {
        ZStack {
            Text(String(describing: editMode))
                .opacity(0)
                .onChange(of: editMode, perform: perform)
            self
        }
    }
}

然后你就可以像这样使用它

代码语言:javascript
复制
struct TestEditModeView: View {
    @Environment(\.editMode) var editMode
    @State private var editModeDescription: String = "nil"
    var body: some View {
        VStack {
            Text(editModeDescription)
            EditButton()
        }
        .onChangeEditMode(editMode: editMode?.wrappedValue) {
            editModeDescription = String(describing: $0)
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57784859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档