在RealmSwift中删除具有关联的数据时崩溃

时间:2020-04-08 15:24:41

标签: swift realm swiftui

我正在使用RealmSwift创建应用程序。

以下实现在删除相关数据时崩溃。

仅删除“ UnderlayerItem”后,成功。 删除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 个答案:

答案 0 :(得分:1)

您无需遍历列表中的对象即可将其删除。就是这样做

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

我相信它会崩溃,因为您正在尝试访问已删除的项目

self.item.underlayerItems