We first looked at Realm way back in Bite #49. It's a great data storage solution for our mobile apps. Today we'll start looking at some of the latest improvements in Realm and the new capabilities they offer. First up is Fine-grained notifications. Let's dive in:
Realm has offered notifications of write operations for a while, they look like this:
let token = realm.addNotificationBlock { notif, realm in
// TODO: viewController.updateUI()
}
These are still around and work great, but it might help to know more about what changed. That's where the new Collection Notifications come in.
Collection notifications give us access the changes that just occurred at a fine-grained level, including the specific indices of insertions, deletions, etc
let results = try! Realm().objects(Spaceship).sorted("name")
let token = results.addNotificationBlock { (changes: RealmCollectionChange) in
// TODO: self.processChanges(changes)
}
changes
here is an enum that looks like this:
public enum RealmCollectionChange<T> {
case Initial(T)
case Update(T, deletions: [Int], insertions: [Int], modifications: [Int])
case Error(NSError)
}
.Update's
values can be easily mapped to NSIndexPath objects suitable for use in table views and collection views.
Here's a complete example showing all of this in action:
class SpaceshipsViewController: UITableViewController {
var notificationToken: NotificationToken? = nil
override func viewDidLoad() {
super.viewDidLoad()
let realm = try! Realm()
let results = realm.objects(Spaceships).filter("maxSpeed > 0")
// 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
}
}
}
deinit {
notificationToken?.stop()
}
}
More info about Realm can be found at realm.io