ObjectiveSugar & ObjectiveRecord

1a8210be06c7e4e4add04eb95ea7964c?s=47 Marin Usalj
September 21, 2013

ObjectiveSugar & ObjectiveRecord

Talk I gave at NSSpain 2013.

ObjectiveC improvements for your everyday life.

1a8210be06c7e4e4add04eb95ea7964c?s=128

Marin Usalj

September 21, 2013
Tweet

Transcript

  1. Supercharged Cocoa development with ObjectiveSugar & ObjectiveRecord Saturday, September 21,

    13
  2. @mneorr mneorr.com Saturday, September 21, 13

  3. Rijeka (Fiume) Saturday, September 21, 13

  4. PROGRAMMERS Saturday, September 21, 13

  5. PROGRAMMERS Cat people Saturday, September 21, 13

  6. PROGRAMMERS Cat people Dog people Saturday, September 21, 13

  7. That’s why I have a hybrid Saturday, September 21, 13

  8. Đuro Saturday, September 21, 13

  9. Saturday, September 21, 13

  10. OSS Saturday, September 21, 13

  11. Saturday, September 21, 13

  12. Kiwi Saturday, September 21, 13

  13. Kiwi Saturday, September 21, 13

  14. Alcatraz Saturday, September 21, 13

  15. Saturday, September 21, 13

  16. The point Saturday, September 21, 13

  17. shorter != better Saturday, September 21, 13

  18. BUT many times, shorter can be better Saturday, September 21,

    13
  19. • Focusing on DOING a task, rather than HOW the

    task is being done • Going too much into implementation can distract you from understanding the context Saturday, September 21, 13
  20. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectContext]; NSEntityDescription *entityDescription

    = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:moc]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFormat: @"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary]; [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES]; [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request error:&error]; if (array == nil) { // Deal with error... } } Saturday, September 21, 13
  21. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Saturday, September 21, 13
  22. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context Saturday, September 21, 13
  23. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? Saturday, September 21, 13
  24. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? A fetch request! Saturday, September 21, 13
  25. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? A fetch request! A predicate Saturday, September 21, 13
  26. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? A fetch request! A predicate ..and a sort descriptor Saturday, September 21, 13
  27. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? A fetch request! A predicate ..and a sort descriptor Error handling Saturday, September 21, 13
  28. - (void)fetchEmployees { NSManagedObjectContext *moc = [self managedObjectConte NSEntityDescription *entityDescription

    = [NSEntityDesc entityForNam NSFetchRequest *request = [[NSFetchRequest alloc] init [request setEntity:entityDescription]; // Set example predicate and sort orderings... NSNumber *minimumSalary = @150000.00; NSPredicate *predicate = [NSPredicate predicateWithFor @"(lastName LIKE[c] 'Worsley [request setPredicate:predicate]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor initWithKey:@"firs [request setSortDescriptors:@[sortDescriptor]]; NSError *error = nil; NSArray *array = [moc executeFetchRequest:request erro if (array == nil) { // Deal with error... } } Referencing a context NSEntityDescription? A fetch request! A predicate ..and a sort descriptor Error handling Fetching Saturday, September 21, 13
  29. Defaults out of the box tweaking when you need it

    Saturday, September 21, 13
  30. NSArray *employees = [Employee all]; Saturday, September 21, 13

  31. NSArray *employees = [Employee where:@{ @"lastName": @"Worsley" }]; Saturday, September

    21, 13
  32. ObjectiveC @[] @{} @# Saturday, September 21, 13

  33. ObjectiveSugar Saturday, September 21, 13

  34. 5.times { puts "hello!" } Saturday, September 21, 13

  35. 5.times { puts "hello!" } for (int i = 0;

    i < 5; i++ ) { NSLog(@"Hello"); } Saturday, September 21, 13
  36. [@5 times:^{ NSLog(@"Hello!"); }]; Saturday, September 21, 13

  37. [@5 times:^{ NSLog(@"Hello!"); }]; [@1 upto:5 do:^(int number) { NSLog(@"The

    number is: %d", number); }]; Saturday, September 21, 13
  38. [cars enumerateObjectsUsingBlock:^(id car, NSUInteger index, BOOL *stop) { NSLog(@"Car: %@",

    car.name); }]; Saturday, September 21, 13
  39. [cars enumerateObjectsUsingBlock:^(id car, NSUInteger index, BOOL *stop) { NSLog(@"Car: %@",

    car.name); }]; [cars each:^(id car) { NSLog(@"Car: %@", car.name); }]; Saturday, September 21, 13
  40. NSDictionary *dict = @{ @"one" : @1, @"two" : @2,

    @"three" : @3 }; [dict each:^(id key, id value) { NSLog(@"Key: %@, Value: %@", key, value); }]; // Key: one, Value: 1 // Key: two, Value: 2 // Key: three, Value: 3 Saturday, September 21, 13
  41. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { } Saturday, September 21, 13

  42. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { ! NSMutableArray *people = [NSMutableArray

    new]; } Saturday, September 21, 13
  43. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { ! NSMutableArray *people = [NSMutableArray

    new]; ! for (NSDictionary *personDict in peopleInDicts) { ! } } Saturday, September 21, 13
  44. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { ! NSMutableArray *people = [NSMutableArray

    new]; ! for (NSDictionary *personDict in peopleInDicts) { ! ! Person *person = [[Person alloc] initWithDictionary:personDict]; ! ! [people addObject:person]; ! } } Saturday, September 21, 13
  45. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { ! NSMutableArray *people = [NSMutableArray

    new]; ! for (NSDictionary *personDict in peopleInDicts) { ! ! Person *person = [[Person alloc] initWithDictionary:personDict]; ! ! [people addObject:person]; ! } ! return [NSArray arrayWithArray:people]; } Saturday, September 21, 13
  46. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { } Saturday, September 21, 13

  47. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { NSArray *people = [peopleInDicts map:^id(NSDictionary

    *personDict) { }]; return people; } Saturday, September 21, 13
  48. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { NSArray *people = [peopleInDicts map:^id(NSDictionary

    *personDict) { ! ! return [[Person alloc] initWithDictionary:personDict]; }]; return people; } Saturday, September 21, 13
  49. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { NSArray *people = [peopleInDicts map:^id(NSDictionary

    *personDict) { ! ! return [[Person alloc] initWithDictionary:personDict]; }]; return people; } @{}, @{}, @{},... Saturday, September 21, 13
  50. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { NSArray *people = [peopleInDicts map:^id(NSDictionary

    *personDict) { ! ! return [[Person alloc] initWithDictionary:personDict]; }]; return people; } @{}, @{}, @{},... <Person 0x22131>, <Person 0x22131>, ... Saturday, September 21, 13
  51. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { NSArray *people = [peopleInDicts map:^id(NSDictionary

    *personDict) { ! ! return [[Person alloc] initWithDictionary:personDict]; }]; return people; } Saturday, September 21, 13
  52. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts { return [peopleInDicts map:^id(NSDictionary *personDict) {

    ! ! return [[Person alloc] initWithDictionary:personDict]; }]; } Saturday, September 21, 13
  53. NSArray - lastObject Saturday, September 21, 13

  54. NSArray - lastObject - firstObject ? Saturday, September 21, 13

  55. Strings Saturday, September 21, 13

  56. [NSString stringWithFormat:@"Hello %@", @"world"]; Saturday, September 21, 13

  57. [NSString stringWithFormat:@"Hello %@", @"world"]; @(@"Hello", @"world") Saturday, September 21, 13

  58. [NSString stringWithFormat:@"Hello %@", @"world"]; @(@"Hello", @"world") NSStringWithFormat(@"Hello %@", @"world"); Saturday,

    September 21, 13
  59. NSString *sentence = @"This is a text-with-numbers 1234"; Saturday, September

    21, 13
  60. NSString *sentence = @"This is a text-with-numbers 1234"; [sentence containsString:@"this

    is a"]; // YES Saturday, September 21, 13
  61. NSString *sentence = @"This is a text-with-numbers 1234"; [sentence containsString:@"this

    is a"]; // YES NSRange range = [self rangeOfString:string options:NSCaseInsensitiveSearch]; return range.location != NSNotFound; Saturday, September 21, 13
  62. unless Saturday, September 21, 13

  63. unless(1 + 1 == 3) { NSLog(@"Math rocks!"); } Saturday,

    September 21, 13
  64. unless(1 + 1 == 3) { NSLog(@"Math rocks!"); } unless(_restaurants)

    { _restaurants = [self fetchRestaurants]; } Saturday, September 21, 13
  65. NSDate Saturday, September 21, 13

  66. “NSDate API rocks!” Saturday, September 21, 13

  67. “NSDate API rocks!” - nobody ever Saturday, September 21, 13

  68. int secondsInMinute = 60; int minutesInHour = 60; int hoursInDay

    = 24; int days = 98 * hoursInDay * minutesInHour * secondsInMinute; NSDate *christmas = [NSDate dateWithTimeInterval:days sinceDate:[NSDate date]]; // 2013-12-25 00:00:00 +0000 Saturday, September 21, 13
  69. int secondsInMinute = 60; int minutesInHour = 60; int hoursInDay

    = 24; int days = 98 * hoursInDay * minutesInHour * secondsInMinute; NSDate *christmas = [NSDate dateWithTimeInterval:days sinceDate:[NSDate date]]; NSDate *christmas = @(98).days.fromNow; // 2013-12-25 00:00:00 +0000 // 2013-12-25 00:00:00 +0000 Saturday, September 21, 13
  70. int secondsInMinute = 60; int minutesInHour = 60; int hoursInDay

    = 24; int days = 98 * hoursInDay * minutesInHour * secondsInMinute; NSDate *christmas = [NSDate dateWithTimeInterval:days sinceDate:[NSDate date]]; NSDate *future = @(24).days.fromNow; // 2013-12-25 00:00:00 +0000 // 2013-12-25 00:00:00 +0000 NSDate *reminder = [@(1).month until:newYearsDay]; Saturday, September 21, 13
  71. CoreData Saturday, September 21, 13

  72. CoreData 3 talks so far Saturday, September 21, 13

  73. ObjectiveRecord Saturday, September 21, 13

  74. // store Person *person = [Person create]; person.firstName = @"Tom";

    person.lastName = @"Cat"; [person save]; [person delete]; // fetch NSArray *people = [Person all]; Saturday, September 21, 13
  75. AppDelegate Saturday, September 21, 13

  76. AppDelegate 160 loc Saturday, September 21, 13

  77. CoreData • creating • fetching • modifying • saving /

    deleting Saturday, September 21, 13
  78. Creating Saturday, September 21, 13

  79. Saturday, September 21, 13

  80. - (void)insertNewObject:(id)sender { NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; NSEntityDescription *entity

    = [[self.fetchedResultsController fetchRequest] entity]; NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; // If appropriate, configure the new managed object. // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template. [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; // Save the context. NSError *error = nil; if (![context 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(); } } Saturday, September 21, 13
  81. NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; Event *event = [Event create:@{

    @"timeStamp": [NSDate date] } inContext:context]; [event save]; Saturday, September 21, 13
  82. Fetching Saturday, September 21, 13

  83. • Create an instance of NSPredicate • Create an instance

    of NSFetchRequest, but you need to talk with NSEntityDescription as well • Fetch and check for errors Saturday, September 21, 13
  84. [Person all]; Saturday, September 21, 13

  85. [Person all]; [Person where:@"name == 'John'"]; Saturday, September 21, 13

  86. [Person all]; [Person where:@"name == 'John'"]; [Person where:@{ @"name": @"John",

    @"isMember": @YES }]; Saturday, September 21, 13
  87. [Person all]; [Person where:@"name == 'John'"]; [Person where:@{ @"name": @"John",

    @"isMember": @YES }]; [Person where:@"name == 'John'" inContext:context]; Saturday, September 21, 13
  88. BYOMOC™ Saturday, September 21, 13

  89. Testing Saturday, September 21, 13

  90. Domain Logic Persistence Saturday, September 21, 13

  91. [[CoreDataManager sharedManager] useInMemoryStore] TestHelper.m Saturday, September 21, 13

  92. Mapping Saturday, September 21, 13

  93. @interface Person : NSManagedObject @property(strong, nonatomic) NSString *firstName; @property(strong, nonatomic)

    NSString *lastName; @property(strong, nonatomic) NSNumber *age; @end Saturday, September 21, 13
  94. { "people": [ { "first_name": "John", "last_name": "Doe", "age": 24

    }, { "first_name": "Mark", "last_name": "Smith", "age": null }! ] } @interface Person : NSManagedObject @property(strong, nonatomic) NSString *firstName; @property(strong, nonatomic) NSString *lastName; @property(strong, nonatomic) NSNumber *age; @end Saturday, September 21, 13
  95. CoreData </3 NSNull Saturday, September 21, 13

  96. • - you need NO AppDelegate code to start, and

    you can still save context on `-applicationWillTerminate:` • - all the important ObjectiveRecord methods have a counterpart with `NSManagedObjectContext` parameter • - ObjectiveRecord supports writing your own NSPredicates as well • - unlike MagicalRecord, does not create NSManagedObjectContexts for you • - unlike MagicalRecord, it doesn't use mr_prefixes. (you can go beat me later about that) • - it's lightweight Saturday, September 21, 13
  97. Thanks Saturday, September 21, 13