Realm Blog

Realm Objective-C & Swift 0.95

We just released version 0.95 of Realm Objective-C and Realm Swift.

Key-Value Observing

Realm objects are now Key-Value Observing compliant for most properties. Using KVO on standalone Realm objects has always worked as normal, but on persisted objects you would only get notifications for changes made directly to the observed object, and not changes made on other threads or via other accessors for the same object. This has now been fixed, and observing properties of persisted objects will now work correctly regardless of how they’re changed. In addition, you can now observe the invalidated property of persisted objects to be notified of when the object is deleted from the Realm.

See the docs for Objective-C or Swift for more information on KVO with Realm, or check out our ReactKit or ReactiveCocoa examples showing them used with Realm.

Realm Configuration

We’ve reworked how you open and configure Realm instances. Rather than a mixture of class methods that register options for a path and overloaded initializers, all options are stored in a Realm configuration object (RLMRealmConfiguration in Objective-C and Realm.Configuration in Swift). This configuration object can be safely passed around between threads to easily create Realm instances for each thread, or can be set as the default configuration to use.

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

// Set either the path for the file or the identifer for an in-memory Realm
// By default config.path will be the Default realm path
config.path = "";
// config.inMemoryIdentifier = @"MyInMemoryRealm";

// Encryption keys, schema versions and migration blocks are now all set on the
// config object rather than registered for a path:
config.encryptionKey = GetKeyFromKeychain();
config.schemaVersion = 10;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
    // do stuff
};

// New feature: a Realm configuration can explicitly list which object classes
// should be stored in the Realm, rather than always including every `RLMObject`
// and `Object` subclass.
config.objectClasses = @[Dog.class, Person.class];

// Either use the configuration to open a Realm:
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

// Or set the configuration used for the default Realm:
[RLMRealmConfiguration setDefaultConfiguration:config];

The following APIs have been deprecated in favor of the new RLMRealmConfiguration class in Realm Objective-C:

Deprecated API New API
+[RLMRealm realmWithPath:readOnly:error:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm realmWithPath:encryptionKey:readOnly:error:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm setEncryptionKey:forRealmsAtPath:] -[RLMRealmConfiguration setEncryptionKey:]
+[RLMRealm inMemoryRealmWithIdentifier:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm defaultRealmPath] +[RLMRealmConfiguration defaultConfiguration]
+[RLMRealm setDefaultRealmPath:] +[RLMRealmConfiguration setDefaultConfiguration:]
+[RLMRealm setDefaultRealmSchemaVersion:withMigrationBlock] RLMRealmConfiguration.schemaVersion and RLMRealmConfiguration.migrationBlock
+[RLMRealm setSchemaVersion:forRealmAtPath:withMigrationBlock:] RLMRealmConfiguration.schemaVersion and RLMRealmConfiguration.migrationBlock
+[RLMRealm migrateRealmAtPath:] +[RLMRealm migrateRealm:]
+[RLMRealm migrateRealmAtPath:encryptionKey:] +[RLMRealm migrateRealm:]

The following APIs have been deprecated in favor of the new Realm.Configuration struct in Realm Swift for Swift 1.2:

Deprecated API New API
Realm.defaultPath Realm.Configuration.defaultConfiguration
Realm(path:readOnly:encryptionKey:error:) Realm(configuration:error:)
Realm(inMemoryIdentifier:) Realm(configuration:error:)
Realm.setEncryptionKey(:forPath:) Realm(configuration:error:)
setDefaultRealmSchemaVersion(schemaVersion:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
setSchemaVersion(schemaVersion:realmPath:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
migrateRealm(path:encryptionKey:) migrateRealm(configuration:)

The following APIs have been deprecated in favor of the new Realm.Configuration struct in Realm Swift for Swift 2.0:

Deprecated API New API
Realm.defaultPath Realm.Configuration.defaultConfiguration
Realm(path:readOnly:encryptionKey:) throws Realm(configuration:) throws
Realm(inMemoryIdentifier:) Realm(configuration:) throws
Realm.setEncryptionKey(:forPath:) Realm(configuration:) throws
setDefaultRealmSchemaVersion(schemaVersion:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
setSchemaVersion(schemaVersion:realmPath:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
migrateRealm(path:encryptionKey:) migrateRealm(configuration:)

The old methods will be removed entirely in a future version.

Class Subsets

The new Realm configuration API also adds the ability to specify what object classes you want to be stored in a given Realm file, rather than having it be all RLMObject and RealmSwift.Object subclasses. This is done by setting the objectClasses property to an array of the class objects you want to be persisted in the Realm.

RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
config.objectClasses = @[MyClass.class, MyOtherClass.class];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
var config = Realm.Configuration()
config.objectTypes = [MyClass.self, MyOtherClass.self]
let realm = Realm(configuration: config)

The main benefit of this is that it makes it much easier to have independent components in your application which use Realm. In previous versions, making a change to an object class would require bumping the schema version for all Realms you open, even ones which would never actually be used to store objects of that type.

Explicitly listing the classes to include also lets Realm skip scanning for RLMObject and RealmSwift.Object subclasses. This can be important for App Extensions. Iterating over all of the registered classes in a process eagerly loads all linked bundles, which in applications linking a large number of frameworks can cause problems with the App Extension memory limit.

Modifying objects while enumerating query results

Previously, Realm’s collection types matched the behavior of the Foundation collections and forbade modifying the collection while enumerating it with for..in. Unfortunately, this combined confusingly with Realm’s live-updating query results. A simple loop like for employee in realm.objects(Employee).filter("hired = false") { employee.hired = true } didn’t actually work because as soon as you set hired = true that object is removed from the Results that you’re enumerating.

To fix this, we’ve made it so that enumerating a Realm collection always enumerates the objects which are in the collection at the beginning of the enumeration. This means that you can freely add or remove items from an RLMArray/List while enumerating it, or modify the values of objects in the Realm while enumerating an RLMResults/Results. For example, you can now safely do the following and have it work as desired:

let realm = Realm()
let dogs = realm.objects(Dog)
realm.write {
  for dog in dogs {
    if dog.age > 10 {
      realm.delete(dog)
    }
    else {
      dog.age += 1
    }
  }
}

Performance Improvements

Adding objects to a Realm via the Swift API has been greatly optimized to bring it in line with the Objective-C API.


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


Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

Get more development news like this