よっしーブログ

iOSエンジニアやってます。SwiftUI勉強中です。

if letでNavigationLink遷移時アニメーションが無くなる

こんにちは。iOSエンジニアをしております。よっしーです。
SwiftUIについて勉強中です、個人アプリリリース目標で頑張っています。

はじめに

今回はNavigationLink遷移時にアニメーションが無くなった事象と解決内容について書きます。

環境

・[Xcode] 13.0
・[Swift] 5.5
・[iOS] 15.0

事象

リストから選択した情報を二つ目の画面へ遷移時に渡し表示するという簡単なアプリになっています。
画面遷移をする際にアニメーションをして遷移するのですが、
アニメーションがされないという問題がありました。

原因

原因は、if letでNavigationLinkを生成した直後に遷移を発火していることが問題です。以下がソースです。

struct ContentView: View {
    
    let fruits = ["りんご", "みかん", "もも", "バナナ"]
        
    @State var selectedFruit: String?
    @State var isActive = false
    
    var body: some View {

        NavigationView {
            VStack {

                // ここのif letでNavigationLinkを生成した直後に遷移を発火しているのが問題
                if let selectedFruit = self.selectedFruit {
                    NavigationLink(isActive: $isActive) {
                        SecoundView(fruit: selectedFruit)
                    } label: {
                        EmptyView()
                    }
                }
                
                List(fruits, id: \.self) { fruit in
                    HStack {
                        Text(fruit)
                        Spacer()
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        self.selectedFruit = fruit
                        self.isActive = true
                    }
                }
            }
        }
    }
}

struct SecoundView: View {
    let fruit: String
    
    var body: some View {
        Text("選択したフルーツ: \(fruit)")
            .font(.title)
    }
}

解決

もちろん強制アンラップはダメでした。Viewを生成した直後は、nullになるからです。
destinationの中でif letを使用することで解決しました。

NavigationLink(isActive: $isActive) {
    // destinationの中でif letを使用する
    if let selectedFruit = self.selectedFruit {
        SecoundView(fruit: selectedFruit)
    }
} label: {
    EmptyView()
}

アニメーションできるようになりました。よかった〜。

まとめ

NavigationLinkのif letで遷移する場合は、destinationの中に記載する。

間違っている点等ございましたら、教えていただけると助かります。

参考リンク

iOSDC2022で書いてくだった方感謝です。
SwiftUIのハマりどころとその回避策/ iOSDC_otsuka - Speaker Deck