UmeTanTan
@UmeTanTan (梅本 良太)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

SwiftUIのNavigationViewの画面を閉じるときに、子ビューから閉じようとしたら閉じれない

解決したいこと

SwiftUIでアプリを開発していています。
画面を閉じる処理を子ビュー側で実装しているのですが、普通のViewでは問題なく子ビュー側で閉じることができたのですが、NavigationViewを使用した時は処理が実行されてませんでした。
暫定処理として、同一画面にて閉じる処理を入れたら、無事動作しました。

NavigationViewの場合で、処理が実行されない理由を教えていただきたいです。

子ビューで閉じる処理を実装している理由は、部品を共通にしたかったからです。

確認用コード

ContentView
import SwiftUI

struct ContentView: View {
    @State var isShown:Bool = false
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
            Button {
                isShown = true;
            } label: {
                Text("ナビゲーションビューを開く")
            }
            .fullScreenCover(isPresented: $isShown) {
                CheckView()
            }
        }
        .padding()
    
    }
}

CheckViewが閉じたい画面となります。

CheckView
import SwiftUI

struct CheckView: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        NavigationView {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
                Text("ナビゲーションビュー")
                // 子ビューにて閉じる処理
                ChildView1()
                ChildView2()
                // 自分で閉じる処理
                Button {
                    dismiss()
                } label: {
                    Text("自分で閉じる")
                }

            }
            .padding()
        }
    }
    /// 同じ階層に子ビューを配置
    struct ChildView2:View {
        @Environment(\.dismiss) var dismiss
        var body: some View {
            Button {
                dismiss()
            } label: {
                Text("子ビュー2にて画面を閉じる")
            }

        }
    }
}

子ビューにて閉じる処理を実装

ChildView1
import SwiftUI

struct ChildView1: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        Button {
            dismiss()
        } label: {
            Text("子ビュー1にて画面を閉じる")
        }

    }
}

結果

結果としては、ChildView1ChildView2では画面を閉じることができず、CheckViewにて直接記載したボタンでしか画面は閉じられませんでした。

以上、よろしくお願いします!

0

1Answer

たぶん@Environment(\.dismiss) var dismissは破棄したいViewにあるものでないと使えないのだと思います。

ContentView
import SwiftUI

struct ContentView: View {
    @State var isShown:Bool = false
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
            Button {
                isShown = true;
            } label: {
                Text("ナビゲーションビューを開く")
            }
            .fullScreenCover(isPresented: $isShown) {
                CheckView()
            }
        }
        .padding()

    }
}
CheckView
import SwiftUI

struct CheckView: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        NavigationView {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
                Text("ナビゲーションビュー")
                // 子ビューにて閉じる処理
                ChildView1(dismiss: dismiss)
                ChildView2(dismiss: dismiss)
                // 自分で閉じる処理
                Button {
                    dismiss()
                } label: {
                    Text("自分で閉じる")
                }

            }
            .padding()
        }
    }
    /// 同じ階層に子ビューを配置
    struct ChildView2: View {
        let dismiss: DismissAction
        var body: some View {
            Button {
                dismiss()
            } label: {
                Text("子ビュー2にて画面を閉じる")
            }

        }
    }
}
ChildView1
import SwiftUI

struct ChildView1: View {
    let dismiss: DismissAction
    var body: some View {
        Button {
            dismiss()
        } label: {
            Text("子ビュー1にて画面を閉じる")
        }
    }
}
1Like

Comments

  1. @UmeTanTan

    Questioner

    回答ありがとうございます!
    ご回答との通りに実装すると、無事に子ビューからでも渡すことができました!
    Navigation Viewだと、制約が増えるのか、そもそも普段のビューでもdismissを渡して閉じた方がよいのか、と悩みどころですね。

Your answer might help someone💌