Reputation: 11710
I'm trying to show some placeholder data when the array is empty. This works in iOS 13.7 but something has changed in iOS 14.3 so when the last item is deleted you get this crash:
Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444
If I comment out testStore.data.isEmpty
and just return the Form
I get no crash.
How can I show placeholder when array is empty in iOS 14.3?
struct Test: Identifiable {
var text: String
var id: String { text }
}
extension Test {
final class Store: ObservableObject {
@Published var data = [Test(text: "Hi"), Test(text: "Bye")]
}
}
struct TestList: View {
@EnvironmentObject var testStore: Test.Store
var body: some View {
Group {
if testStore.data.isEmpty {
Text("Empty")
} else {
Form {
ForEach(testStore.data.indices, id: \.self) { index in
TestRow(test: $testStore.data[index], deleteHandler: { testStore.data.remove(at: index) })
}
}
}
}
}
}
struct TestRow: View {
@Binding var test: Test
let deleteHandler: (() -> ())
var body: some View {
HStack {
Text(test.text)
.font(.headline)
Spacer()
Button(action: deleteHandler, label: Image(systemName: "trash"))
}
}
}
Upvotes: 0
Views: 434
Reputation: 54516
You can use the extension proposed here:
struct Safe<T: RandomAccessCollection & MutableCollection, C: View>: View {
typealias BoundElement = Binding<T.Element>
private let binding: BoundElement
private let content: (BoundElement) -> C
init(_ binding: Binding<T>, index: T.Index, @ViewBuilder content: @escaping (BoundElement) -> C) {
self.content = content
self.binding = .init(get: { binding.wrappedValue[index] },
set: { binding.wrappedValue[index] = $0 })
}
var body: some View {
content(binding)
}
}
Then, if you also want to keep ForEach
instead of List
you can do:
struct TestList: View {
@EnvironmentObject var testStore: Test.Store
var body: some View {
Group {
if testStore.data.isEmpty {
Text("Empty")
} else {
Form {
ForEach(testStore.data.indices, id: \.self) { index in
Safe($testStore.data, index: index) { binding in
TestRow(test: binding, deleteHandler: { testStore.data.remove(at: index) })
}
}
}
}
}
}
}
Upvotes: 1