Diego Freniche / @dfreniche / http://www.freniche.com
Core Data Workshop
Diego Freniche: programmer & teacher
Diego Freniche: programmer & teacher
• @dfreniche
• Freelance Mobile developer: iOS/Android/BB10/
webOS/...
• In a former ...
Before we start...
Before we start...
• Switch OFF phones
Before we start...
• Switch OFF phones
• Been here is funny
Before we start...
• Switch OFF phones
• Been here is funny
• ¡Live the moment!¡Carpe diem!
Before we start...
• Switch OFF phones
• Been here is funny
• ¡Live the moment!¡Carpe diem!
• Ask me a lot. Don’t yawn
What you need (checklist)
• a Mac with OS X capable of running Xcode 4.6.1
• last Xcode 4 installed 4.6.1
• You can also u...
Diego Freniche / http://www.freniche.com
Idea: Creating the Core Data Stack
Diego Freniche / @dfreniche / http://www.freniche.com
The Core Data Stack
Managed Object Context
Persistent Store Coordina...
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
• Use Apple’s code?
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
• Use Apple’s code?
• Really?
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
• Use Apple’s code?
• Really?
• Use a singleton?
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
• Use Apple’s code?
• Really?
• Use a singleton?
• Don’t use ...
Diego Freniche / @dfreniche / http://www.freniche.com
Doubts
• Use Apple’s code?
• Really?
• Use a singleton?
• Don’t use ...
Diego Freniche / @dfreniche / http://www.freniche.com
Apple’s code
Diego Freniche / @dfreniche / http://www.freniche.com
Apple’s code
- (void)saveContext
{
NSError *error = nil;
NSManagedOb...
Diego Freniche / @dfreniche / http://www.freniche.com
Apple’s code problems
• Core Data Stack inside AppDelegate?
• Really...
Diego Freniche / @dfreniche / http://www.freniche.com
Create our own Core Data Stack
Diego Freniche / @dfreniche / http://www.freniche.com
Create our own Core Data Stack
• In one “simple” method
Diego Freniche / @dfreniche / http://www.freniche.com
Create our own Core Data Stack
• In one “simple” method
• Singleton ...
Diego Freniche / @dfreniche / http://www.freniche.com
Create our own Core Data Stack
• In one “simple” method
• Singleton ...
Diego Freniche / @dfreniche / http://www.freniche.com
Dependency injection? Or singletons FTW?
• It depends :-)
Diego Freniche / http://www.freniche.com
Idea: using asserts to check threads
Diego Freniche / http://www.freniche.com
Asserts
• Check if we are running UI code in the UI Thread
• Check if we are NOT ...
Diego Freniche / http://www.freniche.com
Asserts
• Check if we are running UI code in the UI Thread
• Check if we are NOT ...
Diego Freniche / http://www.freniche.com
Idea: create a common UITableView/Core data
class
Diego Freniche / http://www.freniche.com
Idea: use an NSManagedObject subclass
Diego Freniche / @dfreniche / http://www.freniche.com
Entities Design Tips
Diego Freniche / @dfreniche / http://www.freniche.com
Entities Design Tips
• Always add field order
Diego Freniche / @dfreniche / http://www.freniche.com
Entities Design Tips
• Always add field order
• Try to create a good ...
Diego Freniche / @dfreniche / http://www.freniche.com
Entities Design Tips
• Always add field order
• Try to create a good ...
Diego Freniche / @dfreniche / http://www.freniche.com
Extend NSManagedObject
• Editor > Create NSManagedObject subclass......
Diego Freniche / @dfreniche / http://www.freniche.com
Extend NSManagedObject
• overwrite init to call designated initializ...
Diego Freniche / @dfreniche / http://www.freniche.com
Extend NSManagedObject
• overwrite init to call designated initializ...
Diego Freniche / @dfreniche / http://www.freniche.com
Validate Properties
• One for every property, if we want it
• Passin...
Diego Freniche / @dfreniche / http://www.freniche.com
Validate Properties
• One for every property, if we want it
• Passin...
Diego Freniche / @dfreniche / http://www.freniche.com
Validator for operations
• First thing: must call [super ...]
• Usef...
Diego Freniche / @dfreniche / http://www.freniche.com
Validator for operations
• First thing: must call [super ...]
• Usef...
Diego Freniche / @dfreniche / http://www.freniche.com
Support for KVO
• Good for Faults
Diego Freniche / @dfreniche / http://www.freniche.com
Support for KVO
• Good for Faults
- (void)willAccessValueForKey:(NSS...
Diego Freniche / http://www.freniche.com
Idea: use Mogenerator
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator
created by Jonathan 'Wolf' Rentzsch
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator (quoting from the web page)
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator (quoting from the web page)
• http://rentzsch.github.io/...
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator (quoting from the web page)
• http://rentzsch.github.io/...
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator (quoting from the web page)
• http://rentzsch.github.io/...
Diego Freniche / @dfreniche / http://www.freniche.com
Mogenerator (quoting from the web page)
• http://rentzsch.github.io/...
Diego Freniche / @dfreniche / http://www.freniche.com
Installing mogenerator
Diego Freniche / @dfreniche / http://www.freniche.com
Using it
• it’s a script, so we can launch it from command line
• us...
Diego Freniche / @dfreniche / http://www.freniche.com
Using it
• it’s a script, so we can launch it from command line
• us...
Diego Freniche / @dfreniche / http://www.freniche.com
Two classes
• _MyClass.*: machine generated
• *MyClass.*: human edit...
Diego Freniche / @dfreniche / http://www.freniche.com
Two classes
• _MyClass.*: machine generated
• *MyClass.*: human edit...
Diego Freniche / http://www.freniche.com
Two classes
Diego Freniche / http://www.freniche.com
#import "_RetroItem.h"
@interface RetroItem : _RetroItem {}
// Custom logic goes ...
Diego Freniche / http://www.freniche.com
#import "_RetroItem.h"
@interface RetroItem : _RetroItem {}
// Custom logic goes ...
Diego Freniche / http://www.freniche.com
Idea: use Magical Record
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Diego Freniche / http://www.freniche.com
Magical record != avoid Core Data at all costs
• Just a bunch of categories to he...
Upcoming SlideShare
Loading in...5
×

Core data intermediate Workshop at NSSpain 2013

3,214

Published on

Slides from my talk at NSSpain 2013 on Core Data

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,214
On Slideshare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
16
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Core data intermediate Workshop at NSSpain 2013

  1. 1. Diego Freniche / @dfreniche / http://www.freniche.com Core Data Workshop
  2. 2. Diego Freniche: programmer & teacher
  3. 3. Diego Freniche: programmer & teacher • @dfreniche • Freelance Mobile developer: iOS/Android/BB10/ webOS/... • In a former life Java Certifications Collector: SCJP 1.5, SCJP 1.6, SCWCD 1.5, SCBCD 1.3 • Some languages: BASIC, PASCAL, C, C++, Delphi, COBOL, Clipper, Visual Basic, Java, JavaScript, Objective-C Hello, World!
  4. 4. Before we start...
  5. 5. Before we start... • Switch OFF phones
  6. 6. Before we start... • Switch OFF phones • Been here is funny
  7. 7. Before we start... • Switch OFF phones • Been here is funny • ¡Live the moment!¡Carpe diem!
  8. 8. Before we start... • Switch OFF phones • Been here is funny • ¡Live the moment!¡Carpe diem! • Ask me a lot. Don’t yawn
  9. 9. What you need (checklist) • a Mac with OS X capable of running Xcode 4.6.1 • last Xcode 4 installed 4.6.1 • You can also use prerelease software, if you are a registered Apple developer. No support then, sorry :-D • SimPholders installed: http://simpholders.com • SQLLite database browser: http://sqlitebrowser.sourceforge.net • (optional) set $HOME/Library folder visible, using (from a Terminal)
  10. 10. Diego Freniche / http://www.freniche.com Idea: Creating the Core Data Stack
  11. 11. Diego Freniche / @dfreniche / http://www.freniche.com The Core Data Stack Managed Object Context Persistent Store Coordinator Persistent Object Store Managed Object Model
  12. 12. Diego Freniche / @dfreniche / http://www.freniche.com Doubts
  13. 13. Diego Freniche / @dfreniche / http://www.freniche.com Doubts • Use Apple’s code?
  14. 14. Diego Freniche / @dfreniche / http://www.freniche.com Doubts • Use Apple’s code? • Really?
  15. 15. Diego Freniche / @dfreniche / http://www.freniche.com Doubts • Use Apple’s code? • Really? • Use a singleton?
  16. 16. Diego Freniche / @dfreniche / http://www.freniche.com Doubts • Use Apple’s code? • Really? • Use a singleton? • Don’t use a singleton?
  17. 17. Diego Freniche / @dfreniche / http://www.freniche.com Doubts • Use Apple’s code? • Really? • Use a singleton? • Don’t use a singleton? • Use dependency injection?
  18. 18. Diego Freniche / @dfreniche / http://www.freniche.com Apple’s code
  19. 19. Diego Freniche / @dfreniche / http://www.freniche.com Apple’s code - (void)saveContext { NSError *error = nil; NSManagedObjectContext *managedObjectContext = self.managedObjectContext; if (managedObjectContext != nil) { if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { // Replace this implementation with code to handle the error appropriately. // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } } } #pragma mark - Core Data stack // Returns the managed object context for the application. // If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. - (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } // Returns the managed object model for the application. // If the model doesn't already exist, it is created from the application's model. - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) { return _managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Test" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; } // Returns the persistent store coordinator for the application. // If the coordinator doesn't already exist, it is created and the application's store added to it. - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Test.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { /* Replace this implementation with code to handle the error appropriately. abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. Typical reasons for an error here include: * The persistent store is not accessible; * The schema for the persistent store is incompatible with current managed object model. Check the error message to determine what the actual problem was. If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory. If you encounter schema incompatibility errors during development, you can reduce their frequency by: * Simply deleting the existing store: [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil] * Performing automatic lightweight migration by passing the following dictionary as the options parameter: @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details. */ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; } #pragma mark - Application's Documents directory // Returns the URL to the application's Documents directory. - (NSURL *)applicationDocumentsDirectory { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; }
  20. 20. Diego Freniche / @dfreniche / http://www.freniche.com Apple’s code problems • Core Data Stack inside AppDelegate? • Really? • Separation of concerns? • Only one Managed Object Context
  21. 21. Diego Freniche / @dfreniche / http://www.freniche.com Create our own Core Data Stack
  22. 22. Diego Freniche / @dfreniche / http://www.freniche.com Create our own Core Data Stack • In one “simple” method
  23. 23. Diego Freniche / @dfreniche / http://www.freniche.com Create our own Core Data Stack • In one “simple” method • Singleton / not singleton?
  24. 24. Diego Freniche / @dfreniche / http://www.freniche.com Create our own Core Data Stack • In one “simple” method • Singleton / not singleton? • Use both!
  25. 25. Diego Freniche / @dfreniche / http://www.freniche.com Dependency injection? Or singletons FTW? • It depends :-)
  26. 26. Diego Freniche / http://www.freniche.com Idea: using asserts to check threads
  27. 27. Diego Freniche / http://www.freniche.com Asserts • Check if we are running UI code in the UI Thread • Check if we are NOT running Core Data code in the UI Thread
  28. 28. Diego Freniche / http://www.freniche.com Asserts • Check if we are running UI code in the UI Thread • Check if we are NOT running Core Data code in the UI Thread #define DF_ASSERT_MAIN_THREAD [NSThread isMainThread]?:(NSLog(@"NOT IN MAIN THREAD"),abort())
  29. 29. Diego Freniche / http://www.freniche.com Idea: create a common UITableView/Core data class
  30. 30. Diego Freniche / http://www.freniche.com Idea: use an NSManagedObject subclass
  31. 31. Diego Freniche / @dfreniche / http://www.freniche.com Entities Design Tips
  32. 32. Diego Freniche / @dfreniche / http://www.freniche.com Entities Design Tips • Always add field order
  33. 33. Diego Freniche / @dfreniche / http://www.freniche.com Entities Design Tips • Always add field order • Try to create a good UML diagram at first
  34. 34. Diego Freniche / @dfreniche / http://www.freniche.com Entities Design Tips • Always add field order • Try to create a good UML diagram at first • Have an NSString constant with every Entity’s name inside .h
  35. 35. Diego Freniche / @dfreniche / http://www.freniche.com Extend NSManagedObject • Editor > Create NSManagedObject subclass... • creates @dynamic properties • getter / setter generated in runtime (@property in compile time) • Core Data doesn’t know at compile time if the persistent store is going to be XML or a DB (or in-memory)
  36. 36. Diego Freniche / @dfreniche / http://www.freniche.com Extend NSManagedObject • overwrite init to call designated initializer
  37. 37. Diego Freniche / @dfreniche / http://www.freniche.com Extend NSManagedObject • overwrite init to call designated initializer -(id)init { NSManagedObjectContext *context = [[CoreDataStack coreDataStack] managedObjectContext]; return [self initWithEntity:[NSEntityDescription entityForName:kRETROITEM_ENTITY inManagedObjectContext:context ] insertIntoManagedObjectContext:context]; }
  38. 38. Diego Freniche / @dfreniche / http://www.freniche.com Validate Properties • One for every property, if we want it • Passing parameter by reference • It should return YES if validation is passed
  39. 39. Diego Freniche / @dfreniche / http://www.freniche.com Validate Properties • One for every property, if we want it • Passing parameter by reference • It should return YES if validation is passed -(BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError;
  40. 40. Diego Freniche / @dfreniche / http://www.freniche.com Validator for operations • First thing: must call [super ...] • Useful to check business rules (using several properties)
  41. 41. Diego Freniche / @dfreniche / http://www.freniche.com Validator for operations • First thing: must call [super ...] • Useful to check business rules (using several properties) - (BOOL)validateForDelete:(NSError **)error - (BOOL)validateForInsert:(NSError **)error - (BOOL)validateForUpdate:(NSError **)error
  42. 42. Diego Freniche / @dfreniche / http://www.freniche.com Support for KVO • Good for Faults
  43. 43. Diego Freniche / @dfreniche / http://www.freniche.com Support for KVO • Good for Faults - (void)willAccessValueForKey:(NSString *)key
  44. 44. Diego Freniche / http://www.freniche.com Idea: use Mogenerator
  45. 45. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator created by Jonathan 'Wolf' Rentzsch
  46. 46. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator (quoting from the web page)
  47. 47. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator (quoting from the web page) • http://rentzsch.github.io/mogenerator/
  48. 48. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator (quoting from the web page) • http://rentzsch.github.io/mogenerator/ • generates Objective-C code for your Core Data custom classes
  49. 49. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator (quoting from the web page) • http://rentzsch.github.io/mogenerator/ • generates Objective-C code for your Core Data custom classes • Unlike Xcode, mogenerator manages two classes per entity: one for machines, one for humans
  50. 50. Diego Freniche / @dfreniche / http://www.freniche.com Mogenerator (quoting from the web page) • http://rentzsch.github.io/mogenerator/ • generates Objective-C code for your Core Data custom classes • Unlike Xcode, mogenerator manages two classes per entity: one for machines, one for humans • The machine class can always be overwritten to match the data model, with humans’ work effortlessly preserved
  51. 51. Diego Freniche / @dfreniche / http://www.freniche.com Installing mogenerator
  52. 52. Diego Freniche / @dfreniche / http://www.freniche.com Using it • it’s a script, so we can launch it from command line • using iTerm, DTerm, etc. • Best way: to have it inside our project • Create a new Aggregate Target (New Target > Other > Aggregate) • Add Build Phase > Add Run Script
  53. 53. Diego Freniche / @dfreniche / http://www.freniche.com Using it • it’s a script, so we can launch it from command line • using iTerm, DTerm, etc. • Best way: to have it inside our project • Create a new Aggregate Target (New Target > Other > Aggregate) • Add Build Phase > Add Run Script mogenerator --template-var arc=true -m RetroStuffTracker/ RetroStuffTracker.xcdatamodeld/RetroStuffTracker.xcdatamodel/
  54. 54. Diego Freniche / @dfreniche / http://www.freniche.com Two classes • _MyClass.*: machine generated • *MyClass.*: human edited • Never, ever recreate the classes again from the Core Data Model
  55. 55. Diego Freniche / @dfreniche / http://www.freniche.com Two classes • _MyClass.*: machine generated • *MyClass.*: human edited • Never, ever recreate the classes again from the Core Data Model
  56. 56. Diego Freniche / http://www.freniche.com Two classes
  57. 57. Diego Freniche / http://www.freniche.com #import "_RetroItem.h" @interface RetroItem : _RetroItem {} // Custom logic goes here. @end Two classes
  58. 58. Diego Freniche / http://www.freniche.com #import "_RetroItem.h" @interface RetroItem : _RetroItem {} // Custom logic goes here. @end #import "RetroItem.h" @interface RetroItem () // Private interface goes here. @end @implementation RetroItem // Custom logic goes here. @end Two classes
  59. 59. Diego Freniche / http://www.freniche.com Idea: use Magical Record
  60. 60. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs
  61. 61. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code
  62. 62. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code • You have to know your sh*t
  63. 63. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code • You have to know your sh*t • CocoaPods friendly
  64. 64. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code • You have to know your sh*t • CocoaPods friendly • Ideal: use Unit testing + Mogenerator + CocoaPods + Magical Record
  65. 65. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code • You have to know your sh*t • CocoaPods friendly • Ideal: use Unit testing + Mogenerator + CocoaPods + Magical Record • My point: 7 people, 7 ideas, all great
  66. 66. Diego Freniche / http://www.freniche.com Magical record != avoid Core Data at all costs • Just a bunch of categories to help you write less code • You have to know your sh*t • CocoaPods friendly • Ideal: use Unit testing + Mogenerator + CocoaPods + Magical Record • My point: 7 people, 7 ideas, all great • all different
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×