Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Going Down the Core Data Rabbit Hole

Going Down the Core Data Rabbit Hole

Core Data is a great framework that Apple provides to help persist data in your applications. If you have familiarity with other persistence frameworks like N/Hibernate and Entity Framework then you may feel right at home with Core Data! Using SQLite directly can be a real pain, especially if you have little to no C experience. Core Data lets you ignore the actual store used and gives a great interface to make saving information a little more straightforward.

This session will cover the basics and intermediate topics of Core Data and some of the bigger gotchas that Apple's Documentation doesn't necessarily call out. I'll give some of the tips and tricks I've learned over the years of using Core Data so that you have less pain to get started. Core Data is certainly not the most friendly of APIs, but once you learn it, you'll use it all the time.

Aaron Douglas

August 13, 2013
Tweet

More Decks by Aaron Douglas

Other Decks in Technology

Transcript

  1. Who am I? ✦ Aaron Douglas ✦ @astralbodies ✦ Automattic

    (WordPress) ✦ iOS Developer / Android (a little) ✦ Previous Life == Enterprise Java Developer
  2. Who are you? ✦ iOS Developers? Tinkerers? ✦ Anyone use

    SQLite before? ✦ How about Core Data?
  3. SQLite is GREAT ✦ Self-contained ✦ Server-less ✦ Nearly zero

    configuration ✦ Transactional ✦ Written in C / Super portable
  4. SQLite meh ✦ Written in C ✦ No ARC ✦

    Foundation wrappers ✦ Lots of boilerplate Code ✦ Room for archive/unarchive mapping errors
  5. ORM ✦ Object Relational Mapping ✦ Maps tables to real

    objects ✦ Persisting is relatively easy ✦ Less code (usually) ✦ Hibernate, Entity Framework, Ibatis
  6. Why Core Data? ✦ In Appleland for many years -

    OS X Tiger, iPhone OS 3.0 ✦ Xcode visual designer ✦ Validation ✦ Migration ✦ Persist anywhere - SQLite, XML, memory
  7. Core Data Topics ✦ Main moving parts ✦ Managed Object

    ✦ Managed Object Model & Context ✦ Persistent Store ✦ Persistent Store Coordinator ✦ Fetch Requests
  8. Object Contexts ✦ Scratchpad ✦ Each object associated to single

    context ✦ Objects are not transferrable ✦ Nested contexts
  9. Fetching Example NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Appointment" inManagedObjectContext:context]; NSFetchRequest *request

    = [[NSFetchRequest alloc] init]; request.entity = entityDescription; NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"(date >= %@)", startDate]; NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"(date <= %@)", endDate]; NSPredicate *predicate3 = [NSPredicate predicateWithFormat:@"salesRep == %@", [self.salesRepService getSalesRepByGeneracId:salesRepId]]; NSPredicate *predicate4 = [NSPredicate predicateWithFormat:@"active == %@", @YES]; NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2, predicate3, predicate4]]; request.predicate = predicate; NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]; NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"slotNumber" ascending:YES]; request.sortDescriptors = @[sortDescriptor1, sortDescriptor2]; ! NSArray *data = [context executeFetchRequest:request error:&error];
  10. Fetching Example ... NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"(date >= %@)",

    startDate]; NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"(date <= %@)", endDate]; NSPredicate *predicate3 = [NSPredicate predicateWithFormat:@"salesRep == %@", salesRepId]; NSPredicate *predicate4 = [NSPredicate predicateWithFormat:@"active == %@", @YES]; NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2, predicate3, predicate4]]; ! request.predicate = predicate; ...
  11. Fetching Example ... ! NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];

    NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"slotNumber" ascending:YES]; ! request.sortDescriptors = @[sortDescriptor1, sortDescriptor2]; ! ...
  12. Core Data Validation ✦ Models have basic validation rules ✦

    Single property validation ✦ Inter-property validation ✦ Multiple errors
  13. Custom Validation ✦ validate<Key>:error: method in NSManagedObject subclass ✦ Do

    not call directly ✦ Common place for error codes/states
  14. Inter-Property ✦ validateForInsert: validateForUpdate: overrides ✦ Make sure to call

    super ✦ Return NO if invalid; short-circuit if super is NO ✦ Easy to mess up!
  15. Migrations ✦ Changing data models affect users new and existing

    ✦ Need a consistent state of data ✦ Defaults ✦ Field changes
  16. Inferred Limitations ✦ Add & Remove Attributes ✦ Non-optional becomes

    optional ✦ Optional becomes non-optional with default ✦ Renaming entity or property
  17. Thread Confinement ✦ Separate MO Context for each thread ✦

    Share Persistent Store Coordinator ✦ Pass object IDs rather than objects ✦ Track changes with notifications
  18. Undo Management ✦ NSUndoManager ✦ Built-in support in NSManagedObjectContext ✦

    Undo manager is nil in iOS ✦ Simple to use, easy to mess up
  19. Usage NSUndoManager *undoManager = [[NSUndoManager alloc] init]; ! undoManager.levelsOfUndo =

    10; ! context.undoManager = undoManager; ! ... ! [context.undoManager undo];