Realm ObjC & Swift 2.4: Object Notifications!

We’re releasing version 2.4 of Realm Objective‑C and Realm Swift today. In this release, we’re giving our live objects a whole lot more life by adding object-level notifications, so that your app can respond as individual objects update.

Object-Level Notifications

Up until now, if you wanted to know that an object changed, you had to get notifications from collections, which tell you when objects contained in that collection get deleted, inserted, or modified. However, you wouldn’t know which properties have changed. Additionally, creating collections in order to asynchronously observe a single object is awkward, costly and difficult to define when an object can’t easily be uniquely represented by a query.

We’ve long supported KVO to observe property-level changes to single objects, but it’s no secret that KVO is pretty gross, you can only observe a single property per KVO notification, and KVO isn’t cross-platform or cross-language. KVO notifications are also run synchronously, which often means blocking your UI thread 🙀.

Today, we’re shipping object-level notifications so that you’re notified of changes on a single object in the most helpful way possible. Object notifications are powered by a very simple API. Like with collection notifications, you simply add a notification block to the object you’d like to observe. Creating the notification will return a NotificationToken; hold onto it as long as you need notifications for the object.

When the notifications start rolling in, the callback lets you see exactly what changed with its ObjectChange struct, which will expose exactly what properties have changed, or whether the observed object has been deleted:

class Message: Object {
  dynamic var isRead = false
  dynamic var content = ""
}

class MessageController: UIViewController {
  private let notificationToken: NotificationToken

  init(message: Message) {
    notificationToken = message.addNotificationBlock { change in
      switch change {
      case .change(let properties):
        if let readChange = properties.first(where: { $0.name == "isRead" }) {
          self.showReadBadge = readChange.newValue as! Bool
        }
        if let contentChange = properties.first(where: { $0.name == "content" }) {
          self.contentView.textValue = contentChange.newValue as! String
        }
      case .deleted:
        self.handleDeletion()
      case .error(let error):
        self.handleError(error)
      }
    }
  }

  deinit {
    notificationToken.stop()
  }
}

When you’re ready to stop watching the object, you call token.stop(), or simply release the token object.

In summary, you create a notification on a managed object with addNotificationBlock, hold onto the returned NotificationToken instance, and handle whatever updates you need to make to your app inside the callback.

A couple caveats: when list properties change, you won’t see newValue or oldValue data, but the notification will still fire. And if you’re in need of making a synchronous UI write, or just need to skip the notification for a given write, you can still use the interface-driven writes feature by passing the object’s notification token to realm.commitWrite(withoutNotifying: [token]).

Bug Fixes

We’ve fixed several error handling issues when renewing expired authentication tokens for synchronized Realms in this release.

We strongly encourage all Realm Mobile Platform users to update to this version to avoid issues with expiring tokens.

Oh, and we also managed to fix an elusive bug causing a “bad transaction log” exception that’s been haunting us for months! #RaceConditions🏎

Deprecating Swift 2

Supporting legacy Swift versions is a lot of work 😅. With less than 5% of active Realm builders on Swift 2.x and a high cost of maintenance for Swift 2 on our end, this release drops support for Swift 2.x.

That makes Realm Swift 2.3.0 is the last version to support Swift 2.x. We apologize for the inconvenience.

A Note About Xcode 8.3 Beta 1

Apple published the first Xcode 8.3 beta earlier this week. We’ve included a change in this release that fixes a compilation issue with Realm Objective-C.

However, we’re still working through Swift 3.1 compilation issues. Please subscribe to #4586 to be notified of any progress to support Xcode 8.3 with Realm Swift.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.