[SwiftUI] .alert()の記述箇所を気をつけないと子ビューのアラートが表示されなくなる

f:id:bamboohero:20210919171030p:plain

親ビューと子ビューそれぞれでアラートを表示する実装がある場合、.alert() Modifierの記述箇所を気をつけないと、子ビューのアラートが表示されなくなります。

正しく表示されるケースの実装はこちらです。

struct ParentView: View {
    @State var showAlert = false

    var body: some View {
        VStack(spacing: 32) {
            Button("Show parent view alert") {
                showAlert = true
            }
            .alert(isPresented: $showAlert) {
                Alert(title: Text("Parent view alert"))
            }

            ChildView()
        }
    }
}

struct ChildView: View {
    @State var showAlert = false

    var body: some View {
        Button("Show child view alert") {
            showAlert = true
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Child view alert"))
        }
    }
}


f:id:bamboohero:20210919165609p:plain:w300


「Show child view alert」と表示されているボタンをタップすると、子ビューのアラートが表示されます。

f:id:bamboohero:20210919165917p:plain:w300



次は子ビューのアラートが表示されないケースです。

sruct ParentView: View {
    @State var showAlert = false

    var body: some View {
        VStack(spacing: 32) {
            Button("Show parent view alert") {
                showAlert = true
            }
            // .alert(isPresented: $showAlert) {
            //     Alert(title: Text("Parent view alert"))
            //   }

            ChildView()
        }
        // ここに移動
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Parent view alert"))
        }
    }
}

struct ChildView: View {
    @State var showAlert = false

    var body: some View {
        Button("Show child view alert") {
            showAlert = true
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Child view alert"))
        }
    }
}


正しく表示されるケースでは.alert()はビュー階層において同階層に実装されていました。
一方、こちらの実装ではChildViewのコンテナ(VStack)に対して.alert()が実装され、.alert()が複数階層に渡って実装されたことになります。

.alert()を複数の階層で実装してしまうと、下層のアラートが表示されなくなってしまうようです。