F O R D ATA P E R S I S T E N C E : A C O M PA R I S O N W I T H C O R E D ATA J O S H U A D U T T O N : M O B I L E D E V E L O P E R A N D C . T. O . A T H I T L A B S Cactus Charro by Daniel Garrido A P R I L 1 6 , 2 0 1 5
U S I N G R E A L M , E N D E D U P U S I N G C O R E D ATA , B U T WA N T T O M O V E B A C K T O R E A L M J O S H U A D U T T O N : M O B I L E D E V E L O P E R A N D C . T. O . A T H I T L A B S Cactus Charro by Daniel Garrido A P R I L 1 6 , 2 0 1 5
ATA ? • Object graph • XML, Binary, or SQLite data stores • Change management, serializing to disk, and queries • Extremely flexible, but somewhat confusing API X-Ray Bukethead by Daniel Garrido
R N I N G C O R E D ATA • DON’T: • Use a 3rd party library to try to simplify your code (like Magical Record) • Use a singleton (global state can cause problems) • Rely only on Apple’s Core Data Programming Guide X-Ray Bukethead by Daniel Garrido
R N I N G C O R E D ATA • DO: • Read these tuts+ tutorials (Core Data From Scratch): http://code.tutsplus.com/series/core-data-from-scratch--cms-653 • Write your own categories/helpers for boiler plate code. You can use Robert Brown’s code to learn from: https://github.com/rob-brown/RBCoreDataStack • Explicitly state which Managed Object Context you are using (for example, don’t have helper methods that assume you are using your main context) • Read this blog post about a good core data setup: http://martiancraft.com/blog/2015/03/core-data-stack/ X-Ray Bukethead by Daniel Garrido
R E D ATA • All objects (NSManagedObjects) belong to a Managed Object Context. • The Managed Object Context keeps track of changes. Some people call Managed Object Contexts “scratch pads”. • All changes are persisted to disk when the Managed Object Context is saved to the Persistent Store. Flying Taco by Daniel Garrido
R E D ATA // Skipping over lots of boiler plate code to setup the main context // and the persistent store coordinator Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.mainContext]; person.name = @"Joshua"; // Sometime later save the Managed Object Context to the Persistent Store // Many do this when the app quits or goes to the background NSError *error; BOOL success = [self.mainContext save:&error]; Flying Taco by Daniel Garrido
A L M Flying Taco by Daniel Garrido • All objects belong to a Realm (think of a Realm as it’s own database file). • All changes to an object (addition, modification and deletion) have to be done within a write transaction. • Write transactions are atomic and thread safe. This also means that they can block the thread, particularly if several write transactions are queued. • Changes are persisted immediately and available on all threads.
N G : R E A L M // Adding a new object Person *person = [Person new]; person.name = @"Joshua"; // Get the default Realm RLMRealm *realm = [RLMRealm defaultRealm]; // You only need to do this once (per thread) [realm beginWriteTransaction]; [realm addObject:person]; [realm commitWriteTransaction]; // Or [realm transactionWithBlock:^{ [realm addObject:person]; }];
N G : R E A L M // Update an object with a transaction [realm beginWriteTransaction]; person.name = @"Joshua"; [realm commitWriteTransaction]; // Delete an object with a transaction [realm beginWriteTransaction]; [realm deleteObject:person]; [realm commitWriteTransaction];
O R E D ATA NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@“Person"]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] %@", prefix]; fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; NSError *error; NSArray *results = [self.mainContext executeFetchRequest:fetchRequest error:&error]; Nestereo by Daniel Garrido
N G : C O R E D ATA • Two ways to conserve memory: 1. Array with NSManagedObjects that are faults (persistent variables are not yet initialized) 2. NSFetchResultsController: optimized for displaying fetch results in a table view or collection view.
NSFetchRequest with a simple array interface to access the results • Lazy loads • Able to chain queries • Gotcha: results aren’t cached and objects can change (though in the future, results will be frozen during fast enumeration: https://github.com/realm/realm-cocoa/issues/1179)
U R R E N C Y: C O R E D ATA • You can’t pass a Managed Object Context across multiple threads • You can’t pass a Managed Object across multiple threads (you need to query for it or access it by objectId) • Since Managed Object Contexts don’t usually persist to the store immediately, you need a way to sync changes from a context on one thread to a context on another: • Change notifications • Parent/child contexts
U R R E N C Y: R E A L M • You can use the same Realm on multiple threads, but you need to access it separately on each thread • You can’t pass a Realm Object across multiple threads (you need to query for it or access it by primary key) • Since write transactions are atomic, you don’t need to sync changes
U R R E N C Y: R E A L M dispatch_async(backgroundQueue, ^{ // Get realm for this thread RLMRealm *realm = [RLMRealm defaultRealm]; Person *person = [Person objectForPrimaryKey:key]; [realm beginWriteTransaction]; person.name = @"William"; // Commit the write transaction // to make this data available to other threads [realm commitWriteTransaction]; });
U R R E N C Y: R E A L M // Observe Realm notifications for changes on other threads self.token = [realm addNotificationBlock:^(NSString *note, RLMRealm * realm) { [myViewController updateUI]; }]; // Notifications are currently very limited // You are notified that a realm has changed, but not what the changes are // Fine-grained notifications are "coming soon"
R F E AT U R E S • Encryption • In memory realms • Cross-platform Realm files • Migrations • Realm Browser • Sharing Realms between processes (Apple Watch and Extensions) Sombrero Bip-Bop by Daniel Garrido
: A D VA N TA G E S • Fast • Simple API • Follows the fail fast principle • Easy to manage concurrency • Active and helpful development team (Github, Stack Overflow, Twitter, Google Group) • Cross platform
: C U R R E N T L I M I TAT I O N S • Still in beta • No fine-tuned notifications (duplicating NSFetchedResultsController is hard) - fix coming soon • Does not support KVO - fix coming soon • NSDate is truncated to second (use NSTimeInterval instead) - fix coming soon • Does not support nil properties (NSString, NSData, NSNumber, etc.) - fix coming soon • Doesn’t support as many types of queries as Core Data or SQLite - they plan on supporting more in the future