首页 > 解决方案 > 当 Datasource 为 Results 对象时,如何使用 Realm 进行接口驱动的写入

问题描述

接口驱动写入的领域文档表明您可以将记录添加到集合中,如下所示:

func insertItem() throws {
  // Perform an interface-driven write on the main thread:
  collection.realm!.beginWrite()
  collection.insert(Item(), at: 0)
  // And mirror it instantly in the UI
  tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
  // Making sure the change notification doesn't apply the change a second time
  try collection.realm!.commitWrite(withoutNotifying: [token])
}

这似乎意味着表的数据源是一个,因为集合上Array没有insert方法。Results<Item>

collection在这种情况下是什么数据类型?看起来它是一个数组,但我的理解是你不能在数组上创建一个领域通知。

我还读到,将所有 Realm 对象复制到一个数组中(出于性能原因)并不是一个好主意,因为结果是延迟访问的。但是,除非您这样做,否则似乎不可能进行接口驱动的写入。

关于如何正确设置的任何建议?

标签: swiftrealm

解决方案


文档有点含糊,但您的问题的具体答案是,在这种情况下,集合是 List 类型。请参阅Collections的文档。

为了深入了解,这里有一个示例实现。

假设我们有一个 Person 对象,每个人都有一个 Dog 对象的 List 属性。

class PersonClass: Object {
    @objc dynamic var person_name = ""
    let dogs = List<DogClass>()
}

class DogClass: Object {
    @objc dynamic var dog_name = ""
    @objc dynamic var dog_age = 0
    let owners = LinkingObjects(fromType: PersonClass.self, property: "dogs")
}

我们想知道一个特定的人什么时候得到了一只新狗,立即用该狗的信息更新我们的 tableView 并且不会收到事件的 Realm 通知。

这是为 Jean-Luc 的狗设置观察者的代码。

//a class var for the notification and the List.
var dogListNotificationToken: NotificationToken? = nil
var dogList: List<DogClass>? = nil

func doObserveDogList() {
    if let realm = gGetRealm() { //using a singleton Realm for this example
        let personResults = realm.objects(PersonClass.self).filter("name == 'Jean-Luc'")
        let firstPerson = personResults.first
        self.dogList = firstPerson?.dogs
    }

    if self.dogList == nil {
        print("there were no dogs for this person")
        return
    }

    self.dogListNotificationToken = self.dogList!.observe { (changes: RealmCollectionChange) in
        switch changes {
        case .initial:
            print("initial object load complete")
            if let results = self.dogList {
                for d in results {
                    print(d.dog_name, d.dog_age)
                }
            }
            break

        case .update(_, let deletions, let insertions, let modifications):
            print(" handle item delete, insert or mod")

            for index in deletions {
                print("  deleted object at index: \(index)")
            }

            for index in insertions {
                print("  inserted object at index: \(index)")
            }

            for index in modifications {
                print("  modified object at index: \(index)")
            }

            break

        case .error(let error):
            // An error occurred
            fatalError("\(error)")
            break

        }
    }
}

假设 Jean-Luc 得到了一只新狗,所以我们需要将它插入领域,但不想要通知,因为我们想“立即”处理它。

func insertDog() {
    let dogToAdd = DogClass()
    dogToAdd.dog_name = "Number 1"
    dogToAdd.dog_age = 5
    self.dogList?.realm?.beginWrite()
    self.dogList?.insert(dogToAdd, at: 0)
    //insert into tableView/datasource/whatever
    try! self.dogList?.realm!.commitWrite(withoutNotifying: [self.dogListNotificationToken!])
}

以上将导致 Dog 'Number 1' 被添加到 Jean-Luc 的狗列表中,并且在插入时不会触发观察事件。


推荐阅读