環境 xcode11.6
swiftUI
あまり日本語でこの問題に関して言及する記事がなかったので書いてみました。
Pickerに表示したい要素をarrayで定義しておいてForEachで動的に表示したいことってありますよね?うん?
ただ、動的にarrayの要素を削除したりしてpcikerを動かそうとすると
Fatal error: Index out of range
となります。
なぜなら、pickerはそのなかのarrayが変化したことを検知できないのです!!
なので、検知させましょう。
ということで、方法は下記のようにPickerに.id()
を追加します。
Picker(selection: selectd, label: Text("文字色")) {
ForEach(0..<array.count, id: \.self){ id in
self.array[id]
.tag(self.array[id])
}
}
.id(self.uuid)
こうすると、idの引数に渡したself.uuidが更新されたときに、pickerがreloadされて動的に削除したり追加した要素を正しく反映できます。
ちなみに、Pickerのselectionにわたすselectedは、下記のようにカスタムBindingを用意して、setされたらuuidを更新するようにしたりすればいいでしょう。
let selectd = Binding(
get: { },
set: {
self.uuid = UUID()
}
)
こうしてまた迷えるswiftUIエンジニアを救ってしまった。
あ、参考情報はこちらです。
まさにこれで解決できました。
https://stackoverflow.com/questions/60082411/swiftui-hierarchical-picker-with-dynamic-data-crashes
カスタムバインディングについて。
https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-custom-bindings