swift - 当 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 对象复制到一个数组中(出于性能原因)并不是一个好主意,因为结果是延迟访问的。但是,除非您这样做,否则似乎不可能进行接口驱动的写入。
关于如何正确设置的任何建议?
解决方案
文档有点含糊,但您的问题的具体答案是,在这种情况下,集合是 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 的狗列表中,并且在插入时不会触发观察事件。
推荐阅读
- swift - 在 Swift 4 中使用 Twilio 发送消息
- java - 如何在 VSCode 中获取 Java 抽象语法树?
- javascript - Angular 2路由到具有不同url的相同组件
- css - 无论方向如何,如何在 CSS/Bootstrap 中水平堆叠/对齐图像?
- c++ - 在 POS 应用程序中使用 CCO 实现和使用 MSR 服务层
- sql-server - Microsoft SQL Server 2016 - 从哪里获得安装介质?
- python - 即使我明确使用 \r\n,Python 仍会继续编写 unix 样式的换行符
- javascript - 为什么 clearInterval 在我的 discord bot 脚本中不起作用
- mongodb - 使用 Node-Red 将消息异步发送到 MongoDB
- oracle - 将 2 列添加到 oracle 中的现有表中,不为空,并将这些列设置为 PK