List&ForEachの中でNavigationLinkのisActiveを設定するとリストが正常動作しない

この記事は約4分で読めます。

以下のようにListとForEachの中でNavigationLinkのisActiveを設定すると、画面遷移が正常に動作しない。1行目をタップしたはずなのに2行目をタップしたような動作など、動作が不定になり困ったことがありました。

import SwiftUI

struct ListForEach: View {
    var sampleInfo: [String] = ["apple", "orange", "banana"]
    @State var isActive: Bool = false
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<sampleInfo.count, id: \.self) { index in
                NavigationLink(destination: ChildView(sampleString: sampleInfo[index]), isActive: $isActive) {
                        HStack {
                            Text(sampleInfo[index])
                        }
                    }
                }
            }
        }
    }
}

struct ChildView: View {
    var sampleString: String = ""
    var body: some View {
        Text(sampleString + " childview")
    }
}

原因

isActiveはNavigationLinkで画面遷移すると、Trueになります。
また、isActiveがTrueになると、画面遷移が発生します。
そのため、Listの中で繰り返し同じフラグ(isActive)を使用しているため、動作が不定のようになってしまっていたようです。

解決方法

解決方法は、フラグをNavigationLinkの繰り返しごとに分ければ解決することができます。

import SwiftUI

struct ListForEach: View {
    var sampleInfo: [String] = ["apple", "orange", "banana"]
    //NavigationLinkの繰り返しごとにフラグを分けなくてはいけない
    @State var isActive: [Bool] = Array(repeating: false, count: 3)
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<sampleInfo.count, id: \.self) { index in
                NavigationLink(destination: ChildView(sampleString: sampleInfo[index]), isActive: $isActive[index]) {
                        HStack {
                            Text(sampleInfo[index])
                        }
                    }
                }
            }
        }
    }
}

struct ChildView: View {
    var sampleString: String = ""
    var body: some View {
        Text(sampleString + " childview")
    }
}
タイトルとURLをコピーしました