是否可以在 SwiftUI 中创建具有 2 个以上按钮的警报?

Is it possible to create an alert with more than 2 buttons in SwiftUI?

我需要创建一个带有 3 个按钮的提醒,但看起来 SwiftUI 现在只给了我们两个选项:一个按钮或两个按钮。我知道使用 UIKit 可以实现 3 个按钮,但我似乎无法在最新版本的 SwiftUI 中找到解决方法来执行此操作。下面是我的代码,其中我只使用了主要按钮和次要按钮。

Button(action: {
    self.showAlert = true
}){
    Text("press me")
}
.alert(isPresented: self.$showAlert){
     Alert(title: Text("select option"), message: Text("pls help"), primaryButton: Alert.Button.default(Text("yes"), action: {
         print("yes clicked")
         }), secondaryButton: Alert.Button.cancel(Text("no"), action: {
         print("no clicked")
     })
     )
}

.actionSheet、.sheet 和 .popover 是提供自定义警报的选项。考虑这个示例:

import SwiftUI

struct ContentView: View {
    @State private var showModal = false
    @State private var cnt = 0
    var body: some View {
        
        VStack {
            Text("Counter is \(cnt)")
            Button("Show alert") {
                self.showModal = true
            }
        }
        .sheet(isPresented: $showModal,
               onDismiss: {
                print(self.showModal)}) {
                    CustomAlert(message: "This is Modal view",
                              titlesAndActions: [("OK", {}),
                                                 ("Increase", { self.cnt += 1 }),
                                                 ("Cancel", nil)])
        }
    }
}

struct CustomAlert: View {
    @Environment(\.presentationMode) var presentation
    let message: String
    let titlesAndActions: [(title: String, action: (() -> Void)?)] // = [.default(Text("OK"))]
    
    var body: some View {
        VStack {
            Text(message)
            Divider().padding([.leading, .trailing], 40)
            HStack {
                ForEach(titlesAndActions.indices, id: \.self) { i in
                    Button(self.titlesAndActions[i].title) {
                        (self.titlesAndActions[i].action ?? {})()
                        self.presentation.wrappedValue.dismiss()
                    }
                    .padding()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

现在可以在 iOS 15/macOS 12 上使用新版本的警报修饰符:alert(_:isPresented:presenting:actions:).

它的工作方式有点不同,因为不再使用 Alert 结构;您改用常规的 SwiftUI Buttons。添加一个 ButtonRole 以指示哪些按钮执行“取消”操作或“破坏性”操作。将 .keyboardShortcut(.defaultAction) 修饰符添加到按钮以指示它执行主要操作。

例如:

MyView()
    .alert("Test", isPresented: $presentingAlert) {
        Button("one", action: {})
        Button("two", action: {}).keyboardShortcut(.defaultAction)
        Button("three", role: .destructive, action: {})
        Button("four", role: .cancel, action: {})
    }

创建以下警报:

如果想兼容iOS15之前的版本,可以考虑像这样使用actionSheet:

.actionSheet(isPresented: $showActionSheet) {
    ActionSheet(title: Text("Title"), message: Text("Choose one of this three:"), buttons: [
        .default(Text("First")) { },
        .default(Text("Second")) { },
        .default(Text("Third")) { },
        .cancel()
    ])
}