画面遷移にnextViewという変数を用意するパターンはよくある。
nextViewが悪さをしたので備忘録として残そうと考えた。
今回の課題は特定的であり、汎用性の高いものではない。
遷移画面が増えてきた時に、毎回navigationDestinationのModifierとViewで使用する変数(@State
と@Binding
の2つ以上)を用意するのは、冗長なのではないだろうか。
という考えに思い至り、簡単になるような処理を実装してみた。
冗長だという考えに至った状態
// View
}
.navigationDestination(isPresented: $showExhibitView) {
ExhibitView(showExhibitView: $showExhibitView)
.navigationTitle("")
.navigationBarBackButtonHidden(true)
}
.navigationDestination(isPresented: $showArtDetailView) {
if let artInfo = selectedArtInfo {
ArtDetailView(showArtDetailView: $showArtDetailView, artInfo: artInfo)
.navigationTitle("")
.navigationBarBackButtonHidden(true)
}
}
遷移するViewを変数で保持する
以下のように、遷移するViewを変数(transitionNextView)で保持してnavigationDestinationに渡すという処理である。
//Viewの外
@State var transitionNextView: AnyView?
// View
}
.navigationDestination(isPresented: $showNextView) {
if let nextView = transitionNextView {
nextView
.navigationTitle("")
.navigationBarBackButtonHidden(true)
}
}
これで画面遷移が必要になった際、簡単に画面遷移できると考えた…
簡単になったとは、表示のためにnavigationDestinationや変数を用意する必要がなくなった状態のことを指している。
しかし、動作を確認してみると、ある課題が発生した。
画面遷移(NextView)の課題について
課題とは、画面遷移の速度が遅くなったことである。
ほぼノータイムだった画面遷移が0.7秒かかるようになってしまった。
許容することができそうな数値ではあるが、元に戻すことにした。
経緯
そもそもなぜ一つのViewで、navigationDestinationを複数用意しているのか?
navigationDestinationのmodifireを付与する場所を間違えてしまうと、デバッグ時に以下のようにエラーログがXcode上で表示される。
ログが表示されるだけで動作はするが、審査でリジェクトの対象にもなりかねないため修正したいところである。
Do not put a navigation destination modifier inside a "lazy” container, like List
or LazyVStack
. These containers create child views only when needed to render on screen. Add the navigation destination modifier outside these containers so that the navigation stack can always see the destination.
the navigation stack can always see the destination.
とあるように、
NavigationStackが、遷移先のViewを監視できている状態が望ましいようだ。
そのため、NavigationStackを定義しているView内でnavigationDestinationを付与する必要がある。
結果的に、navigationDestinationを同じ場所で複数用意することになった。
NavigationStack {
VStack {
}
.navigationDestination(isPresented: $showView) {
// 表示するView
}
}