2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

iOS15のサポートを外すことを視野に入れたNavigationLinkの書き方

Last updated at Posted at 2023-04-25

はじめに

SwiftUIでプッシュ遷移をする際にNavigationLinkを使用するかと思います。
iOS15以前ではNavigationViewで囲み、内部でNavigationLink(_:destination:isActive:)を使用すれば、プッシュ遷移を実装することができました。
ただ、iOS16でNavigationStackが登場し、上記の関数がDeprecatedになり、以降使用すると、ビルド時に警告が表示されます。
案件等の事情により、現在はiOS15がサポート対象に入っている場合でも、
将来的にサポート対象を外した際に、NavigationLinkの警告表示の対応が必要になるかと思います。
今回の記事では、現在はiOS15だが、今後iOS16を見越したNavigationLinkの書き方を提案したいと思います。

想定読者

最低サポートバージョンにiOS15を含みNavigationLinkを実装する必要がある開発者

開発環境

MacBook Pro 13 inch M1
Xcode14.2

iOS15以前のNavigationLinkの書き方

まず、最低サポートバージョンからiOS15を外した際に警告が表示されるNavigationLinkの書き方は以下になります。

struct ContentView: View {
    @State var isActive = false
    @State var number = 0
    var body: some View {
        NavigationView {
            VStack {
                List(0 ..< 10) { number in
                    Button("\(number)") {
                        isActive = true
                        self.number = number
                    }
                }
                NavigationLink(isActive: $isActive) { // 🙅 Deprecatedと警告される
                    SecondView(number: self.number)
                } label: { EmptyView() }
            }
            .navigationTitle(Text("First"))
        }
    }
}

/// 遷移先のView定義
struct SecondView: View {
    let number: Int
    var body: some View {
        Text("SecondView number:\(number)").font(.title)
    }
}

参考:init(_:destination:isActive:) Deplicated

ちなみに、以下のような書き方だと、最低サポートバージョンがiOS16になっても警告はされません。
iOS16以降のDeprecated対応を避ける意味でこちらの遷移方法を使用する選択肢もあるかもしれません。

// iOS15以前のNavigationLink 警告が出ない書き方
 struct ContentView: View {
    var body: some View {
        NavigationView {
            List(0 ..< 10) { number in
                NavigationLink { // 🙆‍♂️ iOS16でも警告は表示されない
                    SecondView(number: number)
                } label: {
                    Text("\(number)")
                }
            }
            .navigationTitle(Text("First"))
        }
    }
 }

今後iOS15のサポートを切ることを想定したNavigationLinkの書き方

遷移フラグ等で画面遷移を制御したい場合に、
提案としては、iOS16から使用可能な.navigationDestination(isPresented:destination:)に置き換えることを想定して、新たに似たようなExtensionとして.navigationViewDestination(isPresented:destination:)を作成し、最低サポートバージョン変更による移行をスムーズにします。

 struct ContentView: View {
    @State var isActive = false
    @State var number = 0

    var body: some View {
        NavigationView {
            List(0 ..< 10) { number in
                Button("\(number)") {
                    isActive = true
                    self.number = number
                }
            }
            .navigationTitle(Text("First"))
            // 🙆‍♂️ iOS16に切り替えた際に```.navigationDestination(isPresented:destination:)```に変えれば良いだけ
            .navigationViewDestination(isPresented: $isActive) { 
                SecondView(number: number)
            }
        }
    }
 }

 // 新たにExtentionを用意
 extension View {
    func navigationViewDestination(isPresented: Binding<Bool>, @ViewBuilder destination: @escaping () -> some View) -> some View {
        self.background {
            NavigationLink(isActive: isPresented, destination: destination) {
                EmptyView()
            }
        }
    }
 }

【参考】 NavigationStackに置き換えた場合の例

struct ContentView: View {
    @State var isActive = false
    @State var number = 0

    var body: some View {
        NavigationStack { // NavigationView→NavigationStack
            List(0 ..< 10) { number in
                Button("\(number)") {
                    isActive = true
                    self.number = number
                }
            }
            .navigationTitle(Text("First"))
            .navigationDestination(isPresented: $isActive) { // navigationViewDestination→navigationDestination
                SecondView(number: number)
            }
        }
    }
}

参考

APIを差し替えた際にコード修正が最小限で済む方法について参考にさせていただきました。
SwiftUI で「グループスタンプ」というチャット機能を5日間で作った話
NavigtaionStackについて参考にさせていただきました。
iOSDC Japan 2022: SwiftUI Navigation のすべて / アイカワ

2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?