🔥
[SwiftUI]固定Listで選択状態から非選択状態に変える
固定Listでの選択状態の切り替えがうまくいかない
設定画面のような、固定Listで画面遷移も行う画面をSwiftUIで実装していたところ、選択状態が解除されないという事象がありました。
struct ContentView: View {
@State var selection: Int?
var body: some View {
NavigationView {
List(selection: $selection) {
NavigationLink("Item 1", destination: Text("Item 1")).id(1)
NavigationLink("Item 2", destination: Text("Item 2")).id(2)
}.onAppear {
self.selection = nil
}
}
}
}
このコードでは、selectionに選択状態を保存していますが、画面遷移した時にnil
を代入することで選択状態が解除されると考えていましたが、そうはなりませんでした。
StackOverflowでも、同様に悩んでいる人がいました。
環境
この事象は以前よりあるようですが、現在でも発生しています。
- Xcode 12.5.1
- iOS 14.5
解決方法
以下の記事を参考にしましたが、固定Listの場合はうまくいきませんでした。
この記事では、それぞれに.id(UUID())
を追加することで、画面を更新した際に選択状態が解除されるようにしています。
固定Listでうまくいかない原因としては、画面が更新されない
ことだと考えられます。最初のソースコードのように@State
ではうまく画面が更新されないようです。
色々試した結果、ObservableObject
, @Published
と.id(UUID())
を使えばうまくいきました。
class ViewModel: ObservableObject {
@Published var value: Int = 0
}
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
NavigationView {
List {
NavigationLink("Item 1", destination: Text("Item 1")).id(UUID())
NavigationLink("Item 2", destination: Text("Item 2")).id(UUID())
}.onAppear {
self.viewModel.value = 0
}
}
}
}
なんとも気持ちが悪い挙動になっています。@Published var value: Int
はViewでは使っていませんが、更新すると画面全体が再描画されるようで、画面遷移すると選択状態が解除されます。
Discussion