Datasource为Results对象时如何用Realm做接口驱动写
How to Do Interface-driven Write with Realm when Datasource is Results Object
interface-driven write 的 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])
}
这似乎暗示 table 的数据源是 Array
,因为 Results<Item>
集合上没有 insert
方法。
在这种情况下 collection
是什么数据类型?好像是数组,但我的理解是不能在数组上创建Realm通知。
我还读到,将所有 Realm 对象复制到一个数组中(出于性能原因)不是一个好主意,因为结果是延迟访问的。但是除非您这样做,否则接口驱动的写入似乎是不可能的。
关于如何正确设置它有什么建议吗?
文档有点含糊,但对你的问题的具体回答是,在这种情况下,集合是一个列表类型。请参阅 Collections.
的文档
为了深入了解,这里有一个示例实现。
假设我们有一个人对象,每个人都有一个 属性 狗对象列表。
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 得到了一只新狗,所以我们需要将它插入领域,但不需要通知,因为我们想处理它 'immediately'。
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!])
}
以上将导致狗 'Number 1' 被添加到 Jean-Luc 的狗列表中,而插入时不会触发观察事件。
interface-driven write 的 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])
}
这似乎暗示 table 的数据源是 Array
,因为 Results<Item>
集合上没有 insert
方法。
在这种情况下 collection
是什么数据类型?好像是数组,但我的理解是不能在数组上创建Realm通知。
我还读到,将所有 Realm 对象复制到一个数组中(出于性能原因)不是一个好主意,因为结果是延迟访问的。但是除非您这样做,否则接口驱动的写入似乎是不可能的。
关于如何正确设置它有什么建议吗?
文档有点含糊,但对你的问题的具体回答是,在这种情况下,集合是一个列表类型。请参阅 Collections.
的文档为了深入了解,这里有一个示例实现。
假设我们有一个人对象,每个人都有一个 属性 狗对象列表。
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 得到了一只新狗,所以我们需要将它插入领域,但不需要通知,因为我们想处理它 'immediately'。
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!])
}
以上将导致狗 'Number 1' 被添加到 Jean-Luc 的狗列表中,而插入时不会触发观察事件。