我是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_。因此,这些部分将是Category
0名称。
现在,在cellForRowAt
中,我只做这个
let item = frc.object(at: indexPath)
cell.textField.text = item.name
自从我们提供了sectionNameKeyPath
以来,提取结果控制器已经完成了所有的工作,并且已经对部分进行了排序,并且知道哪些Item
在哪些部分中。以上就是用NSFetchedResultsController
加载分区表视图的全部内容。
此外,与Realm集合观测者一样,NSFetchedResultsController
监听更改。在这种情况下,它正在侦听对Item
s的更改。假设用户点击选项卡栏上的另一个选项卡,然后转到应用程序中的其他地方,注意到"的拼写错误;firestartor";并修复它。另一个视图控制器上的frc
会注意到这一变化,并调用其委托方法,在那里它将该行的indexPath交给我,我可以直接更新单元格。我不需要做任何处理来计算索引路径,它只需给我正确的索引路径。
问题:
- Realm是否有像
NSFetchedResultsController
这样的机制,可以轻松处理部分,或者部分是否完全由开发人员决定
RealmCollectionChange的文档说。。。
更改信息有两种格式:针对每种类型的更改,集合中的行索引的简单数组,以及适用于直接传递到UITableView的批更新方法的请求节中的索引路径的数组。
- 我得到的只是行索引的简单数组。你如何获得其他格式?具有索引路径阵列的那个
我认为问题是如何使用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(。
还有很多其他方法可以完成这个过程,但这一种对我们有效