Realm Blog

Realm Cocoa 0.88

We just pushed a Realm Objective-C update to this website and to CocoaPods. Here’s what’s new!

LLDB Support Script

Our Xcode Plugin now comes with a LLDB script which adds support for inspecting persisted RLMObjects, RLMResults and RLMArrays objects in Xcode’s UI, rather than just displaying every property as nil or 0:

Screenshot of Xcode Debugger Console

N.B.: The script currently only supports Objective-C. Swift support is in progress and should be ready by the next release.

invalidate

We’ve added an invalidate method to RLMRealm to make it possible to close long-running (implicit) read transactions, which is useful when doing a large number of writes in parallel.

In order to give you a consistent view of your data, Realm only updates the active version accessed between iterations of the run loop. This means that if you read some data from the Realm and then block the thread on a long-running operation while writing to the Realm on other threads, the version is never updated and Realm has to hold on to intermediate versions of the data which you may not actually need, resulting in the file size growing steadily. (This extra space would eventually be reused by future writes, or could be compacted — for example by calling writeCopyToPath:.) Instead, calling invalidate tells Realm that you no longer need any of the objects you’ve read from the Realm so far, and frees us of tracking intermediate versions of those objects.

For example, in the following code, without the call to invalidate, Realm would have to make a copy of the object modified in each write transaction, since it can’t know that the older version won’t be used after the dispatch_group_wait.

- (void)doWork {
    RLMRealm *realm = [RLMRealm defaultRealm];
    dispatch_group_t g = dispatch_group_create();
    dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // Read some data from the Realm on the current thread
    RLMResults *objects = [ExampleObject objectsWhere:@"boolProperty = NO"];
    NSUInteger startCount = [objects count];

    // Tell Realm that we're done with all of the data we read on this thread
    // Accessing `objects` after this will throw an exception
    [realm invalidate];

    // Mutate some objects on other threads
    for (NSUInteger i = 0; i < 100; ++i) {
        dispatch_group_async(g, q, ^{
            RLMRealm *realm = [RLMRealm defaultRealm];
            [realm beginWriteTransaction];
            ExampleObject *obj = [[ExampleObject objectsWhere:@"boolProperty = NO"]
                                                                       firstObject];
            obj.boolProperty = YES;
            [realm commitWriteTransaction];
        });
    }

    // Wait for the background work to complete
    dispatch_group_wait(g, DISPATCH_TIME_FOREVER);

    // Will be startCount - 100 (assuming startCount > 100)
    // Would be equal to startCount without the call to invalidate since the
    // Realm would be pinned to the same version for the duration of this method
    NSUInteger endCount = [[ExampleObject objectsWhere:@"boolProperty = YES"] count];
}

N.B.: calling invalidate will cause all RLMObjects and RLMResults read from this RLMRealm to be invalidated, meaning you will have to fetch them again if you need to access or edit them.

Automatic Rollback on RLMRealm Deallocation

Deallocating an RLMRealm instance in a write transaction lacking an explicit commit/cancel will now be automatically cancelled instead of committed. A message will be logged whenever this happens. Areas where this occurs should be rectified so that all write transactions be explicitly closed (either by calling commitWriteTransaction or cancelWriteTransaction).

New Features

  • BEGINSWITH, ENDSWITH, CONTAINS, and case-insensitive comparisons are now supported when querying array properties (e.g. [Person objectsWhere:@"ANY dog.name CONTAINS 'a'"] to fetch all people who have a dog whose name contains an ‘a’).
  • RLMRealm now has a method writeCopyToPath: which writes a compacted copy of the Realm’s data to the given file path.
  • The location of the default Realm can now be set by calling +[RLMRealm setDefaultRealmPath:]. This can be used to make unit tests use a different Realm file from your application code (while still being able to use the convenience methods for the default Realm), or just if you want the Realm file in a different place.

Performance Improvements

  • Reading values from RLMResults and RLMArray has been significantly sped up: fast enumeration takes about 30% less time, and objectAtIndex:, firstObject and lastObject take about half as long.
  • Calling firstObject and lastObject on a newly created RLMResults no longer results in the query being run twice.

Bug Fixes

  • We’ve fixed two crashes: one which would occasionally occur when performing write transactions on a large number of threads at once, and one when opening multiple Realm files at once which have different column orderings (due to rearranging properties).
  • The schema version for newly created Realm files is now set to the correct value rather than always being 0.
  • Failing to supply a migration block when one is required now gives a much less confusing error message.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on the mailing list, Stack Overflow, GitHub, and 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