Slide 1

Slide 1 text

U S I N G R E A L M 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

Slide 2

Slide 2 text

O R Cactus Charro by Daniel Garrido

Slide 3

Slide 3 text

W H Y I S TA R T E D 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

Slide 4

Slide 4 text

W H AT I S C O R E D 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

Slide 5

Slide 5 text

A N O T E O N L E A 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

Slide 6

Slide 6 text

A N O T E O N L E A 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

Slide 7

Slide 7 text

X-Ray Bukethead by Daniel Garrido W H AT I S R E A L M ? • A NO-SQL database written specifically for mobile • Cross platform (written in C++ with Cocoa and Java interfaces) • Simple API

Slide 8

Slide 8 text

W R I T I N G : C O 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

Slide 9

Slide 9 text

W R I T I N G : C O 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

Slide 10

Slide 10 text

W R I T I N G : R E 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.

Slide 11

Slide 11 text

Flying Taco by Daniel Garrido W R I T I 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]; }];

Slide 12

Slide 12 text

Flying Taco by Daniel Garrido W R I T I 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];

Slide 13

Slide 13 text

F E T C H I N G : C 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

Slide 14

Slide 14 text

Nestereo by Daniel Garrido F E T C H I 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.

Slide 15

Slide 15 text

Nestereo by Daniel Garrido F E T C H I N G : R E A L M RLMResults *results = [[Person objectsWhere:@"name BEGINSWITH[c] %@", prefix] sortedResultsUsingProperty:@"name" ascending:YES];

Slide 16

Slide 16 text

Nestereo by Daniel Garrido RLMResults • Kind of like a 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)

Slide 17

Slide 17 text

Nestereo by Daniel Garrido RLMResults: counts NSUInteger count = [[Person allObjects] count];

Slide 18

Slide 18 text

Nestereo by Daniel Garrido RLMResults: iteration for (Person *person in [Person allObjects]) { // do something with the person }

Slide 19

Slide 19 text

Nestereo by Daniel Garrido RLMResults: chaining queries RLMResults *peopleWithNamePrefix = [[Person objectsWhere:@"name BEGINSWITH[c] %@", prefix] sortedResultsUsingProperty:@"name" ascending:YES]; RLMResults *femalesWithNamePrefix = [peopleWithNamePrefix objectsWhere:@"gender == 'female'"];

Slide 20

Slide 20 text

Hippy Happy Duck by Daniel Garrido C O N C 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

Slide 21

Slide 21 text

Hippy Happy Duck by Daniel Garrido C O N C 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

Slide 22

Slide 22 text

Hippy Happy Duck by Daniel Garrido C O N C 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]; });

Slide 23

Slide 23 text

Hippy Happy Duck by Daniel Garrido C O N C 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"

Slide 24

Slide 24 text

R E A L M : O T H E 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

Slide 25

Slide 25 text

Sombrero Bip-Bop by Daniel Garrido R E A L M : 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

Slide 26

Slide 26 text

Sombrero Bip-Bop by Daniel Garrido R E A L M : 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

Slide 27

Slide 27 text

D E M O iloveui by Daniel Garrido