【问题标题】:Can you use closure like a named block for ToolbarContent - ToolbarItem你能像 ToolbarContent 的命名块一样使用闭包吗 - ToolbarItem
【发布时间】:2021-09-04 11:52:37
【问题描述】:

我将 ToolbarContent 与 ToolbarItem 一起使用,以便在多个视图中拥有一致的工具栏...工具栏看起来像:

struct ToolBarCancelDeleteAdd: ToolbarContent {
    
    @Binding var deletePressed: Bool
    let cancel: () -> Void
    let deleting: () -> Void
    let adding: () -> Void
    
    var body: some ToolbarContent {
        
        ToolbarItemGroup(placement: .cancellationAction) {
            Button("Cancel", action: cancel )
        }
        
        ToolbarItemGroup(placement: .confirmationAction) {
            if deletePressed {
                Button(action: deleting, label:{Text("Done")})
            } else {
                Button(action: deleting, label:{Text("Delete")})
            }
            Button(action: adding, label: {Image(systemName: "plus")})
        }
    }

在我看来,我正在添加工具栏并提供所需的关闭信息..

        .navigationBarBackButtonHidden(true)
        .navigationTitle("Budget Descriptions")
        .toolbar() { 
            ToolBarCancelDeleteAdd(deletePressed: $deletePressed){
                if self.editMode?.wrappedValue == .active {
                    self.editMode?.wrappedValue = .inactive
                    deletePressed.toggle()
                }
                self.presentationMode.wrappedValue.dismiss()
            }   deleting: {
                if self.editMode?.wrappedValue == .inactive {
                    self.editMode?.wrappedValue = .active
                    deletePressed.toggle()
                } else {
                    self.editMode?.wrappedValue = .inactive
                    deletePressed.toggle()
                }
            } adding: {
                if self.editMode?.wrappedValue == .active {
                    self.editMode?.wrappedValue = .inactive
                }
                self.isAdding.toggle()
            }
        } // END OF TOOLBAR

这一切都很好,我很满意.....除了我在多个视图中执行此代码,如果我需要调整它,我必须转到多个视图来调整它。如果我可以像使用 ViewBuilder 对某些视图所做的那样命名这个闭包内容,那就太好了。这样我就可以以某种方式命名闭包内容......就像......

        .navigationBarBackButtonHidden(true)
        .navigationTitle("Budget Descriptions")
        .toolbar() { 
            ToolBarCancelDeleteAdd(deletePressed: $deletePressed){
                   CancelContent()
            }   deleting: {
                   DeleteContent()            
            } adding: {
                   AddingContent()
            }
        } // END OF TOOLBAR

【问题讨论】:

    标签: swiftui closures toolbar


    【解决方案1】:

    为什么不创建一个包含方法的类

    class ToolbarViewModel: ObservableObject {
        func cancelContent(deletePressed: inout Bool, editMode: inout EditMode) {
            if editMode == .active {
                editMode = .inactive
                deletePressed.toggle()
            }
        }
    
        func deleteContent(deletePressed: inout Bool, editMode: inout EditMode) {
            if editMode == .inactive {
                editMode = .active
                deletePressed.toggle()
            } else {
                editMode = .inactive
                deletePressed.toggle()
            }
        }
    
        func addingContent(isAdding: inout Bool, editMode: inout EditMode) {
            if editMode == .active {
                editMode = .inactive
            }
            isAdding.toggle()
        }
    }
    

    然后你可以在通话中使用它

    struct ContentView: View {
        @Environment(\.presentationMode) var presentationMode
        @StateObject var toolbarViewModel = ToolbarViewModel()
        @State private var deletePressed = false
        @State private var isAdding = false
        @State private var editMode: EditMode = .active
    
        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello, world!")
                        .padding()
                }
                .toolbar {
                    ToolBarCancelDeleteAdd(deletePressed: $deletePressed) {
                        toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: &editMode)
                        presentationMode.wrappedValue.dismiss()
                    } deleting: {
                        toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: &editMode)
                    } adding: {
                        toolbarViewModel.addingContent(isAdding: &isAdding, editMode: &editMode)
                    }
                }
            }
        }
    }
    
    enum EditMode {
        case active, inactive
    }
    

    【讨论】:

    • 嗨,我对这个解决方案寄予厚望,但在实施它时我发现我忽略了包含 editMode 实际上是 ``` @Environment(\.editMode) var editMode ``` 触发删除和移动列表中的行的能力..我发现我无法将其作为类方法中的 inout 传递,并且我还没有找到使环境在子类中可用的方法...
    • 所以来自 SwiftUI-Lab 的 Javier 帮助我解决了使用 @Environment(\.editMode) var editMode 并将其传入和传出上述方法的问题。我非常感谢您派我进入的方向。
    【解决方案2】:

    在上面 Nigel Gee 的建议和 SwiftUI Lab 的 Javier 的帮助下,我有了将代码注入我的 .toolbar 的目标的最终解决方案。它看起来像:

    class ToolbarViewModel: ObservableObject {
        
        func cancelContent(editMode: Binding<EditMode>?) {
        
            if editMode?.wrappedValue == .active {
                editMode?.wrappedValue = .inactive
            }
        }
    
        func deleteContent(deletePressed: inout Bool, editMode: Binding<EditMode>?) {
            
            if editMode?.wrappedValue == .inactive {
                editMode?.wrappedValue = .active
            } else {
                editMode?.wrappedValue = .inactive
            }
        }
    
        func addingContent(isAdding: inout Bool, editMode: Binding<EditMode>?) {
    
            if editMode?.wrappedValue == .active {
                editMode?.wrappedValue = .inactive
            }
            isAdding.toggle()
        }
    }
    
    

    在我看来,我声明:

    
        @Environment(\.editMode) var editMode: Binding<EditMode>?
    
        @StateObject var toolbarViewModel = ToolbarViewModel()
    
    

    工具栏看起来像:

    .toolbar {
        ToolBarCancelDeleteAdd() {
            toolbarViewModel.cancelContent(editMode: editMode)
            presentationMode.wrappedValue.dismiss()
        } deleting: {
            toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: editMode)
        } adding: {
            toolbarViewModel.addingContent(isAdding: &isAdding, editMode: editMode)
        }
    } // END OF TOOLBAR
    
    
    

    【讨论】:

    • 很高兴你把它整理好了。不错?
    猜你喜欢
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多