Cra sh при удалении данных с отношением в RealmSwift - PullRequest
0 голосов
/ 08 апреля 2020

Я создаю приложение с использованием RealmSwift.

При удалении связанных данных произошел сбой следующей реализации.

После удаления только «UnderlayerItem», оно успешно выполнено. Cra sh при удалении UnderlayerItem и удалении Item.

Ошибка:

Поток 1: Исключение: «RLMArray был признан недействительным или объект, содержащий его, был удален. "

Как удалить без сбоев?

struct ListView: View {
    @ObservedObject private var fetcher = Fetcher()
    @State private var title = ""

    var body: some View {
        NavigationView {
            VStack {
                TextField("add", text: $title) {
                    let item = Item()
                    item.title = self.title
                    let realm = try! Realm()
                    try! realm.write {
                        realm.add(item)
                    }
                    self.title = ""
                }

                ForEach(self.fetcher.items) { (item: Item) in
                    NavigationLink(destination: DetailView(item: item, id: item.id)) {
                        Text(item.title)
                    }
                }
            }
        }
    }
}

struct DetailView: View {
    var item: Item
    var id: String
    @State private var title = ""
    @ObservedObject private var fetcher = Fetcher()
    @Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>

    var body: some View {
        VStack {
            TextField("add", text: $title) {
                let realm = try! Realm()

                if let item = realm.objects(Item.self).filter("id == '\(self.id)'").first {
                    try! realm.write() {
                        let underlayerItem = UnderlayerItem()
                        underlayerItem.title = self.title
                        item.underlayerItems.append(underlayerItem)
                    }
                }
                self.title = ""
            }

            ForEach(self.item.underlayerItems) { (underlayerItems: UnderlayerItem) in
                Text(underlayerItems.title)
            }

            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
                self.fetcher.delete(id: self.id)
            }) {
                Text("Delete")
            }
        }
    }
}

class Fetcher: ObservableObject {
    var realm = try! Realm()
    var objectWillChange: ObservableObjectPublisher = .init()
    private(set) var items: Results<Item>
    private var notificationTokens: [NotificationToken] = []

    init() {
        items = realm.objects(Item.self)

        notificationTokens.append(items.observe { _ in
            self.objectWillChange.send()
        })
    }

    func delete(id: String) {
        guard let item = realm.objects(Item.self).filter("id == '\(id)'").first else { return }

        try! realm.write() {
            for underlayerItem in item.underlayerItems {
                realm.delete(realm.objects(UnderlayerItem.self).filter("id == '\(underlayerItem.id)'").first!)
            }
        }

        try! realm.write() {
            realm.delete(item)
        }
    }
}

class Item: Object, Identifiable {
    @objc dynamic var id = NSUUID().uuidString
    @objc dynamic var title = ""
    @objc dynamic var createdAt = NSDate()

    let underlayerItems: List<UnderlayerItem> = List<UnderlayerItem>()

    override static func primaryKey() -> String? {
        return "id"
    }
}

class UnderlayerItem: Object, Identifiable {
    @objc dynamic var id = NSUUID().uuidString
    @objc dynamic var title = ""
    @objc dynamic var createdAt = NSDate()

    override static func primaryKey() -> String? {
        return "id"
    }
}

1 Ответ

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

Вам не нужно перебирать объекты в списке, чтобы удалить их. Просто сделайте это

try! realm.write() {
   realm.delete(item.underlayerItems)
}

Я полагаю, что происходит сбой, потому что вы пытаетесь получить доступ к удаленному элементу

self.item.underlayerItems
...