一个视图中的多个警报不能称为SwiftUI

时间:2019-11-30 12:32:09

标签: ios swift swiftui swiftui-bug

在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!")))
        }
    }
}

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

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

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")))
        }
    }
}

在主视图中仅由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")))
                    }

但是,将名为@State的{​​{1}}变量设置为true时,将永远不会显示上述警报。

我的第一印象是,这可能是Swift中的错误,如果是的话,我会向苹果报告。但是,也许由于我的错误,我正在做的事情无法正常工作。

编辑:

正如下面的答案所阐明的,问题似乎与我的failedLogin试图在已经包含警报的视图中引发警报这一事实有关。显然,在一个视图中不能有多个警报。

3 个答案:

答案 0 :(得分:10)

您可以使用.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)
        }
    }
}

答案 1 :(得分:0)

所以我仍然不是100%知道为什么它不能以这种方式发布警报?但是我只需将警报放在主视图中就可以解决此问题。

我将checkAllOf()变量checkAllOf更改为绑定bool,并在主类中调整了新的状态变量。然后,我只复制了function toggle(i, j) { b = document.getElementById("but_" + i + j) if (!b) return; t = b.innerHTML if (t == "X") { b.innerHTML = "O"; b.setAttribute("style", "color:red; background-color:yellow") } if (t == "O") { b.innerHTML = "X"; b.setAttribute("style", "color:white; background-color:black") } } // Check if board is solved function checkAllOff() { for (var i = 0; i < 5; i++) for (var j = 0; j < 5; j++) { t = document.getElementById("but_" + i + j).innerHTML if (t == "O") return false } return (true); } function press(i, j) { toggle(i, j) toggle(i, j - 1) toggle(i, j + 1) toggle(i + 1, j) toggle(i - 1, j) if (checkAllOff()) { console.log("All lights are out!You win!") } } function generateGrid() { var d = document.getElementById("button-grid"); var table = document.createElement("table"); d.appendChild(table); for (var i = 0; i < 5; i++) { var row = document.createElement("tr"); for (var j = 0; j < 5; j++) { var cell = document.createElement("td"); cell.innerHTML = "<button type=button id=but_" + i + j + " onclick=\"press(" + i + ',' + j + ")\"" + " style=\"color:red; background-color:yellow\"" + ">O</button>"; row.appendChild(cell); } table.appendChild(row); } } window.onload = function() { generateGrid(); };,这似乎可以解决问题。

结构现在看起来像这样

<div align="center" id="button-grid">
  <h1> *** Lights Off *** </h1>
  <h2> Click on buttons until they all turn black </h2>
</div>

和警报相同,但现在在调用@State的类中。

编辑:

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

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

isResetting

这里要注意的是,如果将这些警报中的任何一个放置在Vstack上,一个警报都将不起作用。如果将它们放在单独的视图上,则可以按预期的方式调用它们。

也许这将在以后的更新中得到纠正?同时,这是解决此问题的解决方案。

答案 2 :(得分:0)

就我而言,我通过在警报前添加一个空文本来解决它。

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

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

}

}