realm/realm-cocoa — pull request #833 by tgoyne (2014-08-21 23:10:25+00:00)
Title: [Proposal] Redesign in-memory realms

The current design doesn't really work due to that the idea behind the default realm is that users don't need to pass around references to it, but an in-memory realm ceases to exist as soon as there's no RLMRealms referencing it. This new design abandons the idea of switching the default realm to in-memory, and instead lets the user create in-memory realms directly.

This adds two methods (plus variants of each with a NSError out parameter): +[RLMRealm createMemoryRealm] and -[RLMRealm realmForCurrentThread]. The former unconditionally creates an in-memory realm with an automatically generated backing path (i.e. a *different* realm is created each time, with no caching). The latter returns the receiver if called on the correct thread, or a new RLMRealm instance with the same backing realm as the receiver if not (or a cached RLMRealm instance for persisted realms).

-[RLMRealm realmForCurrentThread] is needed due to that +[RLMRealm realmWithPath:] can't automatically detect that it's being given the path to an in-memory realm. We could make +[RLMRealm memoryRealmAtPath:] public, but that still makes it somewhat annoying to write a function which is passed a RLMRealm as a parameter (which may be either persisted or in-memory) and then dispatches to a background thread. Instead, -[RLMRealm path] returns nil so that the user is not mislead into thinking they can use realmWithPath: (and also just because in-memory realms having a path is an implementation detail that could confuse some users).

Once interprocess realm sharing is working, memoryRealmAtPath: should be made public and documented as being specifically for sharing realms between processes.

The documentation currently does not recommend using realmForCurrentThread for persisted realms. It has the potential to be more efficient than +[RLMRealm realmWithPath:] due to not needing any locks, but it has the downside of sometimes keeping the RLMRealm alive longer, and thus keeping its read transaction open. I also think that the style used in some of our tests of shadowing the main thread's realm object within the dispatched block may be less error prone than using a different name for the background realm.

The actual implementation of in-memory realms in this commit should be considered nothing more than a sanity check of the design.