我正在开发一个带有图标的自定义确认对话框,效果很好.缺点是,在视图修改器中,我只能作为一个内容容器访问所有按钮,因此我不能在它们之间放置分隔符,也不能禁用按钮上的覆盖操作(我必须在调用闭包中这样做).

你知道我如何将单个按钮及其动作向下传递到修改器中吗?

我在玩多个TupleView init,但我不知道如何将它们应用于修改器和视图扩展,更不用说按钮操作了.

enter image description here

struct ContentView: View {
    
    @State private var showConfirmationDialog = false
    @State private var showModifierDialog = false
    
    var body: some View {
        VStack {
            Button("Show Dialog") { showConfirmationDialog = true }
            Button("Show ViewMod Dialog") {
                withAnimation {
                    showModifierDialog = true
                }
            }
            .padding()
        }
        .padding()
        
        // standard confirmationDialog
        .confirmationDialog("Test", isPresented: $showConfirmationDialog) {
            Button { } label: {
                Label("Add completion", systemImage: "checkmark.circle")
            }
            Button { } label: {
                Label("Add Note", systemImage: "note.text.badge.plus")
            }
            Button("Cancel", role: .cancel) {}
        }
        
        // custom confirmationDialog with Icons, Cancel added automatically
        .customConfirmDialog(isPresented: $showModifierDialog) {
            Button {
                // action
                showModifierDialog = false
            } label: {
                Label("Add completion", systemImage: "checkmark.circle")
            }
            Divider() // unfortunately this is still necessary
            Button {
                // action
                showModifierDialog = false
            } label: {
                Label("Add Note", systemImage: "note.text.badge.plus")
            }
        }
    }
}


// *** Custom ConfirmDialog Modifier and View extension

extension View {
    func customConfirmDialog<A: View>(isPresented: Binding<Bool>, @ViewBuilder actions: @escaping () -> A) -> some View {
        return self.modifier(MyCustomModifier(isPresented: isPresented, actions: actions))
    }
}

struct MyCustomModifier<A>: ViewModifier where A: View {
    
    @Binding var isPresented: Bool
    @ViewBuilder let actions: () -> A
    
    func body(content: Content) -> some View {
        ZStack {
            content
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            
            ZStack(alignment: .bottom) {
                if isPresented {
                    Color.primary.opacity(0.2)
                        .ignoresSafeArea()
                        .onTapGesture {
                                isPresented = false
                        }
                        .transition(.opacity)
                }
                
                if isPresented {
                    VStack {
                        GroupBox {
                            actions()
                                .frame(maxWidth: .infinity, alignment: .leading)
                        }
                        
                        GroupBox {
                            Button("Cancel", role: .cancel) {
                                    isPresented = false
                            }
                            .bold()
                            .frame(maxWidth: .infinity, alignment: .center)
                        }
                    }
                    .font(.title3)
                    .padding(8)
                    .transition(.move(edge: .bottom))
                }
            }
        }
        .animation(.easeInOut, value: isPresented)
   }
}

推荐答案

这是许多元组中的第一个(您应该支持所有元组,以便与ViewBuilder兼容)

使用Xcode 14b3/iOS 16测试

extension View {
    func customConfirmDialog<A: View, B: View>(isPresented: Binding<Bool>, @ViewBuilder actions: @escaping () -> TupleView<(A, B)>) -> some View {
        return self.modifier(MyCustomModifier(isPresented: isPresented, actions: {
            let buttons = actions()
            VStack(alignment: .leading) {
                buttons.value.0
                Divider()
                buttons.value.1
            }
        }))
    }
}

demo

Ios相关问答推荐

无法在fastlane和github操作中从react-native 应用程序构建ios

PieChartView未以编程方式显示在屏幕上

Flutter WebRTC:GetUserMedia()不适用于Safari和IOS设备

为什么Reaction-Native-Vision-Camera不能与闪光灯一起使用?

DriverKit驱动程序中可能存在IOBufferMemoyDescriptor泄漏

如何在SwiftUI中扩展双击的可检测区域?

Xamarin Forms CustomPin iOS Render

SwiftUI标题/标题文本背景 colored颜色 屏幕宽度

SwiftUI:.toolbar 不适用于 UITextView

NSError 错误领域: "CBATTErrorDomain" 代码: 128 0x0000000282b111a0

如果使用 .onAppear 设置,为什么 SwiftUI Picker 不显示正确的选定值

SwiftUI 切换语句

Swift 5.7 - 使存在的任何协议符合 Hashable

从父母到子元素的 Swift Pass 事件

为什么 Safari 在使用 iOS 6 设备进行远程调试时显示No Inspectable Applications?

如何用 Swift 圆化 UILabel 的边缘

Xcode 8:函数类型不能有参数标签 destruct 我的构建

如何将自己项目中的类导入 Playground

从 iOS/Android 上的 Web 应用调用本机日期 Select 器

Parse for iOS:try 运行应用程序时出错