From the docs, I'm using something similar to dynamically update a table view based on model changes:
let results = realm.objects(Message).filter("someQuery == 'something'").sorted("timeStamp", ascending: true)
// Observe Results Notifications
notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
guard let tableView = self?.tableView else { return }
switch changes {
case .Initial:
// Results are now populated and can be accessed without blocking the UI
tableView.reloadData()
break
case .Update(_, let deletions, let insertions, let modifications):
// Query results have changed, so apply them to the UITableView
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(insertions.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.deleteRowsAtIndexPaths(deletions.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.reloadRowsAtIndexPaths(modifications.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.endUpdates()
break
case .Error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
break
}
}
The docs don't actual detail how the table's data source delegates get this changed data so I figured a property with a custom getter would do:
var rows: Results<Message> {
let realm = try! Realm()
return result = realm.objects(Message).filter("someQuery == 'something'").sorted("timeStamp", ascending: true)
}
This works well in practice but the comment Results are now populated and can be accessed without blocking the UI
made me question this approach. Should my getter return an empty array until the .Initial
notification has fired within the notification block to ensure the main thread is never blocked?
It's probably not obvious from the change notifications section of the docs, but it's actually covered here in the docs.
Results
objects are live, auto-updating objects. When their values are changed elsewhere in the app (or on a background thread), they will automatically update on the next iteration of the run loop with the new values (There are caveats. Results
on background threads need to be explicitly updated).
The point of the change notifications is to merely tell you that a change has occurred, and the next time you access results
, the new values will already be in there. This is so you can update the UI accordingly.
So, your extra code isn't necessary. Just make sure that when a change notification block is triggered, you're still referring to the same parent results
object when you refresh the UI, and it should just work™. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With