一个视图中的多个警报无法调用 SwiftUI

Vap*_*ant 7 ios swift swiftui

在 swiftUI 中调用警报的方法应该比以往更简单,一个简单的例子是

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

    var body: some View {
        Button(action: {
            self.showingAlert = true
        }) {
            Text("Show Alert")
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Important message"), message: Text("Wear sunscreen"), dismissButton: .default(Text("Got it!")))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,即使我正在调用警报并且可以验证正在调用该方法,我的警报也不会显示。

在我的代码中,我有以下结构

private struct resetButton: View {
    @State var isResetting = false

    var body: some View {
        Button("Reset"){
            self.isResetting = true
        }.alert(isPresented: $isResetting) {
            print("We get here")
            return
                Alert(title: Text("Are you sure?"), message: Text("This will erase your Access Key."), primaryButton: .destructive(Text("Reset")) {
                    clearToken()
                    clearAccessKey()
                    clearUsername()
                    }, secondaryButton: .cancel(Text("Cancel")))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在主视图中简单地由resetButton().

但是,当我按下此按钮时,尽管isResetting等于 true,但不会显示警报。我已经验证我的.alert方法在控制台打印时被调用

我们到了

第一次按下按钮。

但是,警报永远不会显示。

警报在同一视图中的其他地方正确显示

.alert(isPresented: $failedLogin) {
                        self.password = ""
                        return
                            Alert(title: Text("Invalid Login"), message: Text("Please verify your credentials and try again"), dismissButton: .default(Text("Ok")))
                    }
Run Code Online (Sandbox Code Playgroud)

但是,当将@State命名的变量failedLogin设置为 true 时,永远不会出现上述警报。

我的第一印象是这可能是 Swift 中的一个错误,如果是我会向苹果报告。但是,也许我正在做的事情由于我的错误而不起作用。

编辑:

正如下面的答案所阐明的那样,问题似乎与我resetButton()试图在已经包含警报的视图中抛出警报的事实有关。显然,您不能在一个视图中有多个警报。

小智 17

您可以使用 .alert( item: ) 代替 .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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是可接受的答案,因为特定类型的 AlertItem 仅需要一个警报修饰符,即。错误警报与正常选择警报。 (3认同)

Vap*_*ant 5

所以我仍然不能 100% 确定为什么无法以这种方式发布警报?但是我能够通过将警报放在主视图中来解决这个问题。

我将@State变量isResetting更改为绑定 bool 并在主类中调整一个新的状态变量。然后我只是复制了.alert,这似乎解决了问题。

结构现在看起来像这样

private struct resetButton: View {
    @Binding var isResetting: Bool

    var body: some View {
        Button("Reset"){
            self.isResetting = true
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

和警报是相同的,但现在在类调用中resetButton()

编辑:

因此,SwiftUI 似乎不允许您从同一视图中调用多个警报,但是,如果您希望在同一视图中显示多个警报,则有一种解决方法。

您可以从视图内的任何位置调用警报,以便以下解决方案起作用。

private struct exampleAlert: View {
    @State var alert1 = false
    @State var alert2 = false

    var body: some View {
        Vstack{
           Button("alert 1"){
             self.alert1 = true
           }.alert(isPresented: $alert1) {
            Alert(title: Text("Important message"), message: Text("This alert can show"), dismissButton: .default(Text("Got it!")))
        }
           Button("alert 2"){
             self.alert2 = true
           }.alert(isPresented: $alert2) {
            Alert(title: Text("Important message"), message: Text("This alert can also show"), dismissButton: .default(Text("Got it!")))
        }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

这里的问题是,如果将这些警报中的任何一个放置在 Vstack 上,一个将不起作用。如果它们被放置在单独的视图上,那么两者都可以按预期调用。

也许这会在未来的更新中得到纠正?与此同时,这里有一个解决这个问题的解决方案。