如何使Realm集合观察器部分像"NSFetchedResultsController"一样具有感知



我是Realm的新手,我希望它能在CoreData中做一些简单的事情。首先,我将解释它是如何与CoreData一起工作的,然后我将询问是否或如何使用Realm来实现它。

TL;DR:我希望Realm具有与NSFetchedResultsController类似的功能,特别是它如何轻松管理表视图部分。如果你知道答案,你可以跳过下面的细节。

下面是场景。假设我们有一个这样的数据模型:

┌────────────────┐
│Category        │
│ - name         │             ┌────────────────┐
│ - description  │┼─────┐      │Item            │
│ - items        │      │     ┌│ - name         │
│ - dateCreated  │      └────○┼│ - description  │
└────────────────┘            └│ - category     │
│ - dateCreated  │
└────────────────┘

一个CCD_ 2可以有许多CCD_。一个Item有一个Category

假设我们在表视图中显示一些Item。表格视图按Category划分。看起来是这样的:

┌──────────────┐
│Camping       │
│ Axe          │
│ Firestartor  │
│Clothing      │
│ Bug shirt    │
│ Long pants   │
│              │
└──────────────┘

是的,有个打字错误。我们会做到的。露营是一个Category,并显示在一个章节标题中。它的Item是该部分中的行。与Clothing相同,它是一个Category,它在节头中,它的Item是该节中的行。

有了CoreData,这很容易用NSFetchedResultsController实现,比如

let fr = NSFetchRequest<Item> = NSFetchRequest(…)
fr.predicate = …
fr.sortDescriptors = …
let frc = NSFetchedResultsController(fetchRequest: fr, managedObjectContext: moc, sectionNameKeyPath: “category.name”, cacheName: nil)

获取请求fr与Realm查询非常相似。它指定实体以及谓词和排序描述符。在这种情况下,假设排序描述符表示按照类别名称中的项目名称进行排序。

但对于部分,关键是为sectionNameKeyPath参数提供一个值。该值相对于您在提取请求中指定的实体。因此,在这种情况下,category.name是相对于Item的。CCD_ 17具有CCD_ 18并且CCD_。因此,这些部分将是Category0名称。

现在,在cellForRowAt中,我只做这个

let item = frc.object(at: indexPath)
cell.textField.text = item.name

自从我们提供了sectionNameKeyPath以来,提取结果控制器已经完成了所有的工作,并且已经对部分进行了排序,并且知道哪些Item在哪些部分中。以上就是用NSFetchedResultsController加载分区表视图的全部内容。

此外,与Realm集合观测者一样,NSFetchedResultsController监听更改。在这种情况下,它正在侦听对Items的更改。假设用户点击选项卡栏上的另一个选项卡,然后转到应用程序中的其他地方,注意到"的拼写错误;firestartor";并修复它。另一个视图控制器上的frc会注意到这一变化,并调用其委托方法,在那里它将该行的indexPath交给我,我可以直接更新单元格。我不需要做任何处理来计算索引路径,它只需给我正确的索引路径。

问题:

  1. Realm是否有像NSFetchedResultsController这样的机制,可以轻松处理部分,或者部分是否完全由开发人员决定

RealmCollectionChange的文档说。。。

更改信息有两种格式:针对每种类型的更改,集合中的行索引的简单数组,以及适用于直接传递到UITableView的批更新方法的请求节中的索引路径的数组。

  1. 我得到的只是行索引的简单数组。你如何获得其他格式?具有索引路径阵列的那个

我认为问题是如何使用Realm观察器处理谨慎的插入、删除和修改,以便在tableView中应用动画。

让我笼统地处理这类问题,因为我们不知道tableView部分和行是如何填充的。

假设我们在Realm中存储了一堆Person对象,每个Person都有一个name属性。我们将这些人加载到tableView数据源中,并让一个观察者观察这些结果。以下是展示如何通过索引访问每个对象的"勇气">

func observePeople() {
self.peopleToken = self.peopleResults!.observe { changes in
switch changes {
case .initial(let people):
print("  initial object load complete")
for person in people {
print("(person.name)")
}
case .update(let persons, let deletions, let insertions, let modifications):
for index in deletions {
let deletedPerson = persons[index]
print("  deletedAccount: (deletedPerson.name)")
}
for index in insertions {
let insertedPerson = persons[index]
print("  insertedAccount: (insertedPerson.name)")
}
for index in modifications {
let modifiedPerson = persons[index]
print("  modifiedAccount: (modifiedPerson.name)")
}
case .error(let error):
print(error.localizedDescription)
}
}
}

假设一个用户将他们的姓氏从Jones修改为Smith。观察代码的这一部分将执行

for index in modifications {
let modifiedPerson = persons[index]
print("  modifiedPerson: (modifiedPerson.name)")
}

这将打印到控制台

modifiedPerson: Smith

要将动画添加到具有行和节的tableView中,请将case语句中的上述代码替换或扩充为:

case .update(_, let deletions, let insertions, let modifications):
... determine the section. for example, first char is A=0, B=1, C=2 etc
tableView.beginUpdates()behavior.
tableView.deleteRows(at: deletions.map({ getPath(for: $0) )}),
with: .automatic)
tableView.insertRows(at: insertions.map({ getPath(for: $0) }),
with: .automatic)
tableView.reloadRows(at: modifications.map({ getPath(for: $0) }),
with: .automatic)
tableView.endUpdates()

然后是确定该对象在dataSource中的位置并返回该对象的索引路径的函数,支持动画。

func getPathFor(myPerson: PersonClass) {
//determine which object this is in the array and return it's indexPath
return indexPath
}

例如,如果我们使用的是A、B、C部分,而用户Jones是J部分中的第一个人,那么这将是第9部分第0行。例如,let jones=IndexPath(行:0,节:9(。

还有很多其他方法可以完成这个过程,但这一种对我们有效

最新更新