We just pushed a Realm Objective-C update to this website and to CocoaPods. Here’s what’s new!
RLMResults
RLMArray
has been split into two classes: RLMArray
and RLMResults
. RLMArray
is now used only for to-many properties on RLMObject
classes, while RLMResults
is used for all of the querying and sorting methods. This was done to reflect that the two actually had fairly different APIs (for example, RLMResults
does not have addObject:
), and they’re expected to diverge further as we add change notifications for queries.
The migration for this should be as simple as replacing RLMArray *
with RLMResults *
in all of the places that the compiler complains about.
To go with this, arraySortedByProperty:ascending:
has been renamed to sortedResultsUsingProperty:ascending:
, and addObjectsFromArray:
has been renamed to addObjects:
to reflect the fact that you can pass any enumerable object to it (such as NSArray
, RLMArray
, or RLMResults
).
// Before
RLMArray *objects = [[UserObject allObjects] arraySortedByProperty:@"karma"
ascending:YES];
// After
RLMResults *objects = [[UserObject allObjects] sortedResultsUsingProperty:@"karma"
ascending:YES];
Migrations
The API for migrations has also changed a bit. You now call setSchemaVersion:withMigrationBlock:
to register a global migration handler which will be called whenever you open a Realm file with a lower schema version. This simplifies working with multiple Realm files, and ensures that the schema version gets set correctly for newly created Realm files.
You can now create and delete objects during migrations using the new createObject:withObject
and deleteObject:
methods on RLMMigration
.
[RLMRealm setSchemaVersion:5 withMigrationBlock:^(RLMMigration *migration,
NSUInteger oldSchemaVersion) {
// Version 5 added support for multiple users, so add a User object for
// the implicit User in previous versions and associate all existing data
// with it
if (oldSchemaVersion == 4) {
User *user = [migration createObject:@"User"
withObject:@{@"name": @"Default User"}];
[migration enumerateObjects:@"Message" block:^(RLMObject *oldObject,
RLMObject *newObject) {
[user.messages addObject:newObject];
}];
}
}];
In-memory realms
In-memory realms have been redesigned to be more useful and work when shared between threads. You now obtain an in-memory Realm by calling +[RLMRealm inMemoryRealmWithIdentifier:]
, where the identifier is an arbitrary string. Much as with persisted realms, each thread which wants to access the Realm should call inMemoryRealmWithIdentifier:
with the same identifier to get a local reference to the in-memory Realm.
Because the data for in-memory Realms is never persisted to disk, it remains valid only as long as you hold a reference to a RLMRealm
object for that Realm. As this combined confusingly with the default Realm, the default Realm can no longer be made in-memory.
@interface MyViewController : UITableViewController<UITableViewDataSource>
@property (nonatomic, strong) RLMRealm *realm;
@property (nonatomic, strong) RLMNotificationToken *notification;
@property (nonatomic, strong) RLMResults *data;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.realm = [RLMRealm inMemoryRealmWithIdentifier:kRealmId]
self.data = [DemoObject allObjectsInRealm:self.realm];
self.notification = [self.realm addNotificationBlock:^(NSString *notification,
RLMRealm *realm) {
// No need to update self.data as it's automatically updated after each
// write transaction is committed (and not until it's committed)
[self.tableView reloadData];
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.data.count;
}
- (void)doStuff {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
RLMRealm *realm = [RLMRealm inMemoryRealmWithIdentifier:kRealmId]
[realm beginWriteTransaction];
// freely modify the data without having to copy everything first
// ...
// triggers a notification on the main thread which updates the UI with
// the new data
[realm commitWriteTransaction];
});
}
@end
Transaction rollback
Write transactions can now be cancelled and their modifications rolled back with the method -[RLMRealm cancelWriteTransaction]
. This reverts all changes made to objects, restores deleted objects, and deletes newly created objects.
[realm beginWriteTransaction];
DogObject *newDog = [DogObject createInDefaultRealmWithObject:@{@"name": @"Rex"}];
// createOwnerForDog:error: might fail, in which case we don't want the
// newly created Dog object to be saved
OwnerObject *owner = [self createOwnerForDog:newDog error:&error];
if (owner) {
[realm addObject:owner];
[realm commitWriteTransaction];
}
else {
NSLog(@"Failed to create owner object: %@", error);
// Deletes newDog from the Realm
[realm cancelWriteTransaction];
}
Partial updates with create or update
createOrUpdateInRealm:withObject:
and friends now support partially updating existing objects. Passing a dictionary with keys set for only some of the fields will leave the existing values alone for all other fields if the object exists already (or use the default values if it does not). Naturally the primary key field must always be present, of course.
// Set the email field of the existing User object with primary key `key` to
// `newEmail`, and leave the rest of the properties unchanged
[User createOrUpdateInDefaultRealmWithObject:@{@"key": key, @"email": newEmail}];
Query improvements
RLMArray
and RLMResults
can now be sorted by multiple properties at once using sortedResultsUsingDescriptors:
, which takes an NSArray
of RLMSortDescriptors
describing which properties to sort on.
RLMArray
properties can now be queried using objectsWhere:
and objectsWithPredicate:
.
Querying a sorted RLMResults
object now returns results with the same sort order.
Fixed crashes on IN clauses with thousands of items and queries for equality on indexed NSString
properties.
!= is now supported on one-to-one relationship properties.
Swift on OS X
Now that Xcode 6.1 is out, the precompiled binaries once again support Swift on OS X.
Assorted other things
RLMRealm
now has a deleteAllObjects
method to easily clear the Realm file.
Creating RLMRealm
instances on background threads is now significantly faster.
Fixed a case where rearranging the properties on an existing RLMObject
class didn’t work correctly.
Fixed a crash when assigning to a RLMArray
property on a non-persisted RLMObject
instance.
Added error messages when a RLMArray
property with an invalid protocol or a RLMObject
subclass nested within another Swift class are encountered.
Passing an object already persisted in a Realm to addObject:
is once again a no-op rather than an error. Trying to add a persisted object to a different Realm is still an error.
Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on the mailing list, StackOverflow, GitHub, twitter and email.
Receive news and updates from Realm straight to your inbox