LoginSignup
22
15

More than 3 years have passed since last update.

[SwiftUI] NavigationLinkの遷移先を動的に変更する

Posted at

https://qiita.com/noppefoxwolf/items/c10c50cbefb7896107fd
で解説したように、型消去を利用することで遷移先の画面を事前に指定することなく動的に与えることが出来ます。
今回はNavigationLinkでも同様のことが出来たので解説します。
一点、NavigationLinkはButtonの機能も有しているため扱いが多少異なります。
このエントリでは、以下のようにEmptyViewを入れることでNavigationLinkをほぼ純粋な画面遷移のObserverとして利用しています。

NavigationLink(destination: destination, tag: tag, selection: $selection) {
    EmptyView()
}

NavigationLinkはsheetと違い、identifarableによって遷移先を変更する機能は無いのですが遷移事態を要求することが出来るイニシャライザが存在します。


public init<V>(destination: Destination, tag: V, selection: Binding<V?>, @ViewBuilder label: () -> Label) where V : Hashable

tagで指定した値がselectionに流れることで、destinationをpushするような挙動になります。
これを利用して、selection代入時に型消去したdestinationを更新することで一つのNavigationLinkを複数の箇所やボタン以外から制御できるようになります。

struct ContentView: View {
    private let defaultTag: Int = 8888
    @State var destination: AnyView? = nil
    @State var tag: Int? = nil

    var body: some View {
        NavigationView {
            VStack  {
                Button(action: {
                    self.destination = AnyView(Text("child 1"))
                    self.tag = self.defaultTag
                }) {
                    Text("tap 1")
                }
                Button(action: {
                    self.destination = AnyView(Text("child 2"))
                    self.tag = self.defaultTag
                }) {
                    Text("tap 2")
                }
                NavigationLink(destination: destination, tag: defaultTag, selection: $tag) {
                    EmptyView()
                }
            }
        }
    }
}

原理としては、tagがbindingされているので同じクラスでdestinationを定義すれば、更新時にbodyが呼ばれてNavigationLinkの遷移先が入った状態で遷移するイメージです。

22
15
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
15