前提・実現したいこと
親のViewの中でList Viewを作り、行を子供のViewで表示する構成です。
子Viewでは、PickerやStepperで元の配列の要素を直接参照しています。
この状態でListから行を削除(左スワイプ)すると、子Viewで配列の範囲外アクセスでクラッシュしてしまいます。
下記のサンプルでは簡略化してStringの読み出しにしていますが、同様の症状になります。
発生している問題・エラーメッセージ
Listから行を削除すると、子Viewで以下のエラーが発生します。
Thread 1: Fatal Error: Index out of range
デバッガでindex値を確認すると、確かに行削除する前には存在していたが削除で範囲外になったindexでアクセスしています。
SceneDelegate.swiftは以下のように変更しています。
let contentView = ContentView().environmentObject(Test())
該当のソースコード
SwiftUI
1import SwiftUI 2 3struct Data: Hashable, Identifiable { 4 let id = UUID() 5 let name: String 6} 7class Test: ObservableObject { 8 @Published var datas = [Data]() 9 10 init() { 11 datas.append(Data(name: "A")) 12 datas.append(Data(name: "B")) 13 } 14 15 func index(_ data: Data) -> Int { 16 return (datas.firstIndex(where: { $0.id == data.id })!) 17 } 18} 19 20struct RowView1: View { 21 @EnvironmentObject var test: Test 22 let index: Int 23 24 var body: some View { 25 Text(test.datas[index].name) 26 } 27} 28 29struct RowView2: View { 30 @EnvironmentObject var test: Test 31 var data: Data 32 var index: Int { 33 test.datas.firstIndex(where: { $0.id == data.id })! 34 } 35 36 var body: some View { 37 Text(test.datas[index].name) 38 } 39} 40 41struct ContentView: View { 42 @EnvironmentObject var test: Test 43 44 var body: some View { 45 List { 46 ForEach(test.datas) { data in 47 RowView1(index: self.test.index(data)).environmentObject(self.test) 48// RowView2(data: data).environmentObject(self.test) 49// Text(self.test.datas[self.test.index(data)].name) 50 }.onDelete { offsets in 51 self.test.datas.remove(atOffsets: offsets) 52 } 53 } 54 } 55}
試したこと
コード中でコメントアウトしている、引数をindexではなくオブジェクトを渡すRowView2()でもクラッシュします。
Thread 1: Fatal Error: Unexpectedly found nil while unwrapping an Optional value
削除済オブジェクトのidで配列を探しているようです。
また、もう一つのコメントアウトのように、子供のViewを作らずに親Viewの中で処理を直接記述すると意図通りに動作しました。
しかし、実際に実現したい行の処理は大きいため子供のViewを作りたいのでこの方法では回避できません。
iPadOS13.1,13.3,13.4いずれも同様の症状でした。
EnvironmentObjectで監視対象にして行削除すればListが正しく更新表示される仕様だと思うのですが、Viewをまたぐ構成には対応していないのでしょうか?
仕様の誤解やコードの間違えなどがあったらご指摘よろしくお願いします。
補足情報(FW/ツールのバージョンなど)
環境はXcode Version 11.4で、iPadシミュレータとiPadOS13.4の実機で確認しています。
回答2件
あなたの回答
tips
プレビュー