How can I have two alerts on one view in SwiftUI?

前端 未结 4 1455
闹比i
闹比i 2020-12-10 03:02

I want to have two unique alerts attached to the same Button view. When I use the code below, only the alert on the bottom works.

I\'m using the officia

相关标签:
4条回答
  • 2020-12-10 03:33

    There's a variation on this solution which only uses one state variable rather than two. It uses the fact that there is another .alert() form which takes an Identifiable item rather than a Bool, so extra information can be passed in that:

    struct AlertIdentifier: Identifiable {
        enum Choice {
            case first, second
        }
    
        var id: Choice
    }
    
    struct ContentView: View {
        @State private var alertIdentifier: AlertIdentifier?
    
        var body: some View {
            HStack {
                Button("Show First Alert") {
                    self.alertIdentifier = AlertIdentifier(id: .first)
                }
                Button("Show Second Alert") {
                    self.alertIdentifier = AlertIdentifier(id: .second)
                }
            }
            .alert(item: $alertIdentifier) { alert in
                switch alert.id {
                case .first:
                    return Alert(title: Text("First Alert"),
                                 message: Text("This is the first alert"))
                case .second:
                    return Alert(title: Text("Second Alert"),
                                 message: Text("This is the second alert"))
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 03:33
    extension Alert:Identifiable{
        public var id:String { "\(self)" }
    }
    
    @State var alert:Alert?
    
    Button(action: {
        if Bool.random() {
            alert = Alert(title: Text("Alert 1"))
        } else {
            alert = Alert(title: Text("Alert 2"))
        }
    }) {
        Text("Show random alert")
    }
    .alert(item:$alert) { $0 }
    
    0 讨论(0)
  • 2020-12-10 03:44

    I improved a litle Ben's answer. You can show multiple alerts dynamically by using .alert(item:) instead .alert(isPresented:):

    struct AlertItem: Identifiable {
        var id = UUID()
        var title: Text
        var message: Text?
        var dismissButton: Alert.Button?
    }
    
    struct ContentView: View {
    
        @State private var alertItem: AlertItem?
    
        var body: some View {
            VStack {
                Button("First Alert") {
                    self.alertItem = AlertItem(title: Text("First Alert"), message: Text("Message"))
                }
                Button("Second Alert") {
                    self.alertItem = AlertItem(title: Text("Second Alert"), message: nil, dismissButton: .cancel(Text("Some Cancel")))
                }
                Button("Third Alert") {
                    self.alertItem = AlertItem(title: Text("Third Alert"))
                }
            }
            .alert(item: $alertItem) { alertItem in
                Alert(title: alertItem.title, message: alertItem.message, dismissButton: alertItem.dismissButton)
            }
        }
    }
    
    0 讨论(0)
  • The second call to .alert(isPresented) is overriding the first. What you really want is one Binding<Bool> to denote whether the alert is presented, and some setting for which alert should be returned from the closure following .alert(isPresented). You could use a Bool for this, but I went ahead and did it with an enum, as that scales to more than two alerts.

    enum ActiveAlert {
        case first, second
    }
    
    struct ToggleView: View {
        @State private var showAlert = false
        @State private var activeAlert: ActiveAlert = .first
    
        var body: some View {
    
            Button(action: {
                if Bool.random() {
                    self.activeAlert = .first
                } else {
                    self.activeAlert = .second
                }
                self.showAlert = true
            }) {
                Text("Show random alert")
            }
            .alert(isPresented: $showAlert) {
                switch activeAlert {
                case .first:
                    return Alert(title: Text("First Alert"), message: Text("This is the first alert"))
                case .second:
                    return Alert(title: Text("Second Alert"), message: Text("This is the second alert"))
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题