Неустранимая ошибка: индекс выходит за пределы диапазона при добавлении и удалении из массива с помощью MVVM.IOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Неустранимая ошибка: индекс выходит за пределы диапазона при добавлении и удалении из массива с помощью MVVM.

Сообщение Anonymous »

Я пытаюсь отобразить массив структур Word в дочерних TextFields, используя архитектуру MVVM, передав привязку к структуре Word дочернему элементу. Существует кнопка для вставки нового пустого слова Word в массив в позиции 0, который заполняется через цикл ForEach в дочерние элементы. Однако, если текстовое поле останется пустым и фокус изменится, я хотел бы удалить этот элемент из родительского массива. Я передал функцию для этого в родительском цикле ForEach. Наконец, в модификаторе OnChange дочернего элемента я вызываю эту функцию, если oldValue равен тому, который потерял фокус, и isEmpty имеет значение true. Но это приводит к фатальной ошибке: Индекс вне диапазона.
При отладке кажется, что код успешно удалил нужный элемент из массива, и что ошибка возникает при последующих проходах цикл ForEach перебирает массив слов. Как я могу это исправить? Весь мой код приведен ниже.
Родительский код
struct Word: Identifiable, Equatable {
var id: String
var word: String
var definition: String?

init(_ word: String, definition: String?) {
self.word = word
self.definition = definition
self.id = UUID().uuidString
}

static func ==(lhs: Word, rhs: Word) -> Bool {
return lhs.id == rhs.id
}
}

class CardViewModel: ObservableObject {

var word: Binding
@Published var loading: Bool = false

init(word: Binding) {
self.word = word
}

}

enum Focusable: Hashable {
case none
case row(id: String)
}

struct CardView: View {

@ObservedObject var vm: CardViewModel

@FocusState var focused: Focusable?

let onEmpty: () -> Void // delete the word!

var body: some View {
VStack(spacing: 0) {
HStack { TextField("", text: vm.word.word)
.font(.title)
.focused($focused, equals: .row(id: vm.word.id))

; Spacer() }

if vm.loading == true {
Text("Loading...")
.frame(maxWidth: .infinity, alignment: .leading)
}

if let definition = vm.word.definition.wrappedValue {
Text(definition)
.frame(maxWidth: .infinity, alignment: .leading)
}

}
.onChange(of: focused) { oldValue, newValue in

if oldValue == .row(id: vm.word.wrappedValue.id) && vm.word.wrappedValue.word.isEmpty {
onEmpty()
}
}

}
}

Дочерний код
import SwiftUI

class StudyViewModel: ObservableObject {

@Published var words: [Word] =
[
Word("sonder", definition: "The realization that each passerby has a life as vivid as your own."),
[...]
]

}

struct StudyView: View {

@Namespace private var namespace

@State private var cardsHeight: CGFloat = 0

@FocusState var focusedReminder: Focusable?

@StateObject var vm: StudyViewModel = StudyViewModel()

var body: some View {

VStack(spacing: 20) {
HStack {
Image(systemName: "gear")
Spacer()
Button {
// add action here
addWordCard()
} label: {
Image(systemName: "plus.circle")
}
.tint(.black)

}
.font(.title)
ScrollView {
VStack(spacing: 20) {
ForEach($vm.words) { $word in
CardView(vm: CardViewModel(word: $word), focused: _focusedReminder) {
deleteWord($word.wrappedValue)
}
}
}
}
}

}
}

// Helper Functions
extension StudyView {

private func addWordCard() {
withAnimation(.spring) {
let new_word = Word("", definition: nil)
vm.words.insert(new_word, at: 0)
focusedReminder = .row(id: new_word.id)
}
}

private func deleteWord(_ word: Word) {
withAnimation(.spring) {

// vm.words.removeAll { $0.id == word.id }
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/793 ... -with-mvvm
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»