Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Programming with Realm

Reactive Programming with Realm

This talk gives an introduction into the basic concepts of Realm and some insights how it works under the hood. Building on these basics, it ended up in exploring together with the audience in a live coding session, how just Realm alone can be central to the architecture of reactive applications.

Marius Rackwitz

May 22, 2016
Tweet

More Decks by Marius Rackwitz

Other Decks in Programming

Transcript

  1. class Person : Object { dynamic var name = ""

    dynamic var age = 0 let children = List<Person>() let parents = LinkingObjects(fromType: Person.self, property: "children") }
  2. All retrieved objects are just pointers to their data. @interface

    RLMObjectBase () { realm::Row _row; } @end namespace realm { class Row { TableRef m_table; size_t m_row_ndx; } }
  3. Live Objects class Message : Object { dynamic var text

    = "" } let realm = try! Realm() let feed = realm.objects(Message) feed.count // => 0 let hello = Message() hello.text = "Hello!" try! realm.write { realm.add(hello) } feed.count // => 1 !
  4. File-wide Observation // Observe Realm Notifications let token = realm.addNotificationBlock

    { notification, realm in viewController.updateUI() } // later token.stop()
  5. Fine-grained Notifications let results = realm.objects(Person).filter("age > 5") // 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 } }
  6. Key-Value-Observing func addObservers() { self.addObserver(self, forKeyPath: "entry.title", options: [], context:

    nil) self.addObserver(self, forKeyPath: "entry.date", options: [], context: nil) } override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if keyPath == "entry.title" { self.textLabel!.text = entry.title } else if keyPath == "entry.date" { self.detailTextLabel.text = entry.date.description } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } }
  7. Key-Value-Observing // e.g. with ReactKit (self.textLabel!, "text") <~ KVO.stream(self, "entry.title")

    (self.detailTextLabel!, "text") <~ KVO.stream(self, "entry.date") |> map { $0!.description as NSString }