【SwiftUI】Alert を連続表示しようとすると2つ目が出ない問題と対処方法

ボタンタップ時などで alert(isPresented: Binding<Bool> を使った Alert の表示方法については以前にこちらの記事で紹介しました。

その際は触れなかったのですが、連続して表示しようとすると2つ目のダイアログが表示されないという不具合なのか仕様なのかよくわからない現象に遭遇します(2020年11月9日現在のSwiftUI最新バージョンで確認済み)。

今回はその対処方法について紹介します。

Alert を連続表示しようとすると2つ目が出ない問題と対処方法

例えば、選択肢のダイアログを出した後、OKボタンのみの結果表示のダイアログを連続で表示したい場合、以下のようなコードを考えると思います。

これ自体は何ら問題ないのですが、このままだと2つ目が表示されません。

struct ContentView: View {
    
    @State private var showingAlert = false
    
    enum AlertType {
        case select
        case complete
    }
    @State private var alertType: AlertType = .select
    
    var body: some View {
        Button("タップしてアラート表示") {
            showingAlert = true
            alertType = .select
        }
        .alert(isPresented: $showingAlert) {
            switch alertType {
            case .select:
                return Alert(title: Text("会社員辞めますか?"), primaryButton: .default(Text("辞める"), action: {
                    showingAlert = true
                    alertType = .complete
                }), secondaryButton: .cancel())
            case .complete:
                return Alert(title: Text("フリーランスになりました。"), message: nil, dismissButton: .default(Text("OK")))
            }
        }
    }
}

で、どう対処したかというと、

単純に少し時間を置いてから表示してみると期待通りの動きをしてくれます。

例えば以下のような感じです。

case .select:
    return Alert(title: Text("会社員辞めますか?"), primaryButton: .default(Text("辞める"), action: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            showingAlert = true
            alertType = .complete
        }
    }), secondaryButton: .cancel())

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1)

このように、0.1秒間を置いてから2つ目を表示しています。

ただ、0.1秒が適切かどうかは不明です。ちなみに、0.01秒でもうまく行きました

時間の問題というよりかは、ライフサイクルの問題のような気がします。

以上、同様の問題で困っている方の一助になれば幸いです。

1件のコメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です