SwiftUI 2.0 / Xcode 12 中父视图和子视图的警报

atd*_*nsm 5 alert swiftui

有人可以向我解释为什么这在 SwiftUI 2.0 / iOS 14 / Xcode 12 中不起作用以及有效的解决方法吗?AlertOne 工作正常,但 AlertTwo 不行。我正在尝试对父视图和子视图(嵌套)发出警报。如果需要,您可以将其插入 Xcode 进行测试。谢谢。

import SwiftUI

struct ContentView: View {
    @State private var alertOne = false

    var body: some View {
        VStack {
            Button("Alert One") {
                self.alertOne.toggle()
            }
            TestView().padding()
        }
        .alert(isPresented: $alertOne) {
            Alert(title: Text("Alert One"), dismissButton: .default(Text("Got it!")))
        }
    }
}

struct TestView: View {
    @State private var alertTwo = false
    
    var body: some View {
        Button("Alert Two") {
            self.alertTwo.toggle()
        }
        .alert(isPresented: $alertTwo) {
            Alert(title: Text("Alert Two"), dismissButton: .default(Text("Got it!")))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

vac*_*ama 4

这是构建代码的一种可能的方法:

struct ContentView: View {
    @State private var showAlert = false
    @State private var alert: Alert? = nil

    var body: some View {
        VStack {
            Button("Alert One") {
                alert = Alert(title: Text("Alert One"), dismissButton: .default(Text("Got it!")))
                self.showAlert.toggle()
            }
            TestView(showAlert: $showAlert, alert: $alert).padding()
        }
        .alert(isPresented: $showAlert) {
            alert!
        }
    }
}

struct TestView: View {
    @Binding var showAlert: Bool
    @Binding var alert: Alert?
    
    var body: some View {
        Button("Alert Two") {
            alert = Alert(title: Text("Alert Two"), dismissButton: .default(Text("Got it!")))
            self.showAlert.toggle()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是使用新类型的替代方案IdentifiableAlert。这使您可以摆脱单独的情况,并且只要将 an分配给showAlert即可显示警报:IdentfiableAlertalert

struct IdentifiableAlert: Identifiable {
    let alert: Alert
    let id = UUID()
}

struct ContentView: View {
    @State private var alert: IdentifiableAlert? = nil

    var body: some View {
        VStack {
            Button("Alert One") {
                alert = IdentifiableAlert(alert: Alert(title: Text("Alert One"), dismissButton: .default(Text("Got it!"))))
            }
            TestView(alert: $alert).padding()
        }
        .alert(item: $alert) { alert in
            alert.alert
        }
    }
}

struct TestView: View {
    @Binding var alert: IdentifiableAlert?
    
    var body: some View {
        Button("Alert Two") {
            alert = IdentifiableAlert(alert: Alert(title: Text("Alert Two"), dismissButton: .default(Text("Got it!"))))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个方便的扩展,可以将 anAlert变成 an IdentifiableAlert()

extension Alert {
    func identifiable() -> IdentifiableAlert { IdentifiableAlert(alert: self) }
}
Run Code Online (Sandbox Code Playgroud)

所以这:

alert = IdentifiableAlert(alert: Alert(title: Text("Alert Two"), dismissButton: .default(Text("Got it!"))))
Run Code Online (Sandbox Code Playgroud)

可以用这个代替:

alert = Alert(title: Text("Alert Two"), dismissButton: .default(Text("Got it!"))).identifiable()
Run Code Online (Sandbox Code Playgroud)