Ошибка удаления записей из списка и области SwiftUI - PullRequest
0 голосов
/ 16 апреля 2020

Кто-нибудь смог успешно интегрировать Realm с SwiftUI, особенно удаляя записи / строки из SwiftUI List? Я пробовал несколько разных методов, но независимо от того, что я делаю, я получаю ту же ошибку. Прочитав некоторые связанные темы, я обнаружил, что у других людей такая же проблема.

Следующий код успешно представляет все элементы из Realm в SwiftUI List, я могу создать новые и они отображаются В списке, как и ожидалось, мои проблемы возникают, когда я пытаюсь удалить записи из списка, нажимая кнопку вручную или проводя влево, чтобы удалить выбранную строку, я получаю ошибку Индекс выходит за границы.

Любая идея, что может быть причиной ошибки?

Вот мой код:

Модель царства

class Dog: Object {
    @objc dynamic var name = ""
    @objc dynamic var age = 0
    @objc dynamic var createdAt = NSDate()

    @objc dynamic var userID = UUID().uuidString
    override static func primaryKey() -> String? {
        return "userID"
    }
}

Код SwiftUI

class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {
    var results: Results<Element>

    private var token: NotificationToken!

    init(results: Results<Element>) {
        self.results = results
        lateInit()
    }
    func lateInit() {
        token = results.observe { [weak self] _ in
            self?.objectWillChange.send()
        }
    }
    deinit {
        token.invalidate()
    }
}

struct DogRow: View {
    var dog = Dog()
    var body: some View {
        HStack {
            Text(dog.name)
            Text("\(dog.age)")
        }
    }
}


struct ContentView : View {

    @ObservedObject var dogs = BindableResults(results: try! Realm().objects(Dog.self))

    var body: some View {
        VStack{

        List{
            ForEach(dogs.results, id: \.name) { dog in
                DogRow(dog: dog)
            }.onDelete(perform: deleteRow )
        }

            Button(action: {
                try! realm.write {
                    realm.delete(self.dogs.results[0])
                }
            }){
                Text("Delete User")
            }
        }
    }

    private func deleteRow(with indexSet: IndexSet){
        indexSet.forEach ({ index in
            try! realm.write {
                realm.delete(self.dogs.results[index])
            }
        })
    }
}

Ошибка

Завершение работы приложения из-за необусловленного исключения «RLMException», причина: «Индекс 23 выходит за пределы (должен быть меньше 23).»

Конечно, 23 изменения в зависимости от того, сколько элементов в базе данных Realm, в этом случае у меня было 24 записи, когда я проводил и нажал кнопку удаления.

FYI - ошибка указывает на файл AppDelegate с Thread 1: signal SIGABRT .

1 Ответ

1 голос
/ 16 апреля 2020

Вот пример того, как я это делаю. Это без операций с областями, но я надеюсь, что вы поймете, куда вы можете поместить материал с областями. (Я также почти никогда не использую объекты области напрямую, а вместо этого преобразую их в структуры или классы.)

import Foundation
import Realm
import Combine
import SwiftUI

struct dogs: Hashable {
  let name: String
}

class RealmObserverModel: ObservableObject {

  var didChange = PassthroughSubject<Void, Never>()
  @Published var dogsList: [dogs] = [dogs(name: "Dog 1"), dogs(name: "Dog 2")]

  // get your realm objects here and set it to
  // the @Publsished var
  func getDogs() {
    let count = dogsList.count + 1
    dogsList.append(dogs(name: "Dog \(count)"))
  }

  // get your realm objects here and set it to
  // the @Publsished var
  func deletetDogs() {
   _ = dogsList.popLast()
  }
}

/// Master View
struct DogView: View {
  @EnvironmentObject var observer: RealmObserverModel

  var body: some View {

    VStack{
      DogsListView(dogsList: $observer.dogsList)

      HStack{
      Button(action: {
        self.observer.getDogs()
      }) {
      Text("Get more dogs")
      }

        Button(action: {
          self.observer.deletetDogs()
        }) {
        Text("Delete dogs")
        }
      }
    }
  }
}

// List Subview wiht Binding
struct DogsListView: View {
  @Binding var dogsList: [dogs]

  var body: some View {
    VStack{
      List{
        ForEach(dogsList, id:\.self) { dog in
          Text("\(dog.name)")
        }
      }
    }
  }
}

struct DogView_Previews: PreviewProvider {
  static var previews: some View {
    DogView().environmentObject(RealmObserverModel())
  }
}
...