【SwiftUI】NavigationStackで一気にルートビューに戻る方法

この記事からわかること

  • SwiftUINavigationStack使い方
  • 孫ビューからルートビューまで一気に戻る方法
  • dismissを使用した遷移操作

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Swift UIでNavigationStackを使用した画面遷移機能を実装時にルートビューまで一気に戻る方法をまとめていきます。

孫ビューからルートビューまで一気に戻る方法

孫ビューまで遷移した状態から子ビューをスキップしてルートビューまで画面を戻すにはNavigationStackの引数にパス情報を保持させる方法を取ることで実装できます。

NavigationStack(path: $path) {

}

例えば以下は「数値の増加とともに深い階層に潜り込んでいくプログラム」です。この場合、遷移するとpathの中にはどんどん遷移履歴が格納されていきます。

【SwiftUI】NavigationPathとNavigationStack(path:root:)の使い方!
struct TestNavigationView: View {
    
    @State  private var path: [Int] = []
    @State  var num:Int = 0
    
    var body: some View {
        NavigationStack(path: $path) {
            List{
                Text("\(num)")
                Button {
                    num += 1
                    path.append(num)
                } label: {
                    Text("Num Add")
                }
            }
            .navigationDestination(for: Int.self) { num in
                ChildView(path: $path,num: $num)
            }
        }.onChange(of: path) { _ in
            print(path)  // [1]  → [1, 2] → ....
        }
    }
}

struct ChildView: View {
    @Binding  var path:[Int]
    @Binding  var num:Int
    var body: some View {
        List{
            Text("\(num)")
            
            Button {
                num += 1
                path.append(num)
            } label: {
                Text("Num Add")
            }
            
            Button {
                num -= 1
                path.removeLast()
            } label: {
                Text("1つ戻る")
            }
            Button {
                num = 0
                path.removeAll()
            } label: {
                Text("ルートビューまで一気に戻る")
            }
        }
        .navigationTitle("ChildView")
        .navigationBarBackButtonHidden(true)
    }
}

ルートビューまで戻るには配列形式で管理している遷移履歴の中身をremoveAllメソッドで空にすることで実装することができます。

パス情報を保持させない状態で実装する

先ほどの形式ではなく、以下のようなシンプルなNavigationStackを使用している場合には一気にルートビューに戻る方法は用意されていないので自前で実装する必要があります。

NavigationStack {

}

方法としてはdismissメソッドを戻りたい回数分実行することで実装することができます。具体的には子側から戻るためのdismissメソッドをクロージャーで渡し、孫側から親のメソッドを実行させます。しかしこの方法の場合は間の子ビューも一瞬表示されるような遷移になるので注意してください。例えば以下は孫ビューからルートビュー(2個上)まで戻したい場合です。

struct TestNavigationView: View {
    var body: some View {
        NavigationStack {
            NavigationLink("ChildView", destination: ChildView())
        }
    }
}

struct ChildView: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        VStack{
            Text("ChildView")
            NavigationLink("GrandChildView", destination: GrandChildView(parentFunction: {dismiss()}))
        }
    }
}

struct GrandChildView: View {
    @Environment(\.dismiss) var dismiss
    var parentFunction:() -> Void
    var body: some View {
        VStack{
            Text("GrandChildView")
            Button {
                dismiss()
                parentFunction()
            } label: {
                Text("ルートビューまで戻る")
            }   
        }
    }
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index