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

ObjectiveSugar & ObjectiveRecord

Marin Usalj
September 21, 2013

ObjectiveSugar & ObjectiveRecord

Talk I gave at NSSpain 2013.

ObjectiveC improvements for your everyday life.

Marin Usalj

September 21, 2013
Tweet

More Decks by Marin Usalj

Other Decks in Programming

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  4. PROGRAMMERS
    Saturday, September 21, 13

    View full-size slide

  5. PROGRAMMERS
    Cat people
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. Đuro
    Saturday, September 21, 13

    View full-size slide

  9. Saturday, September 21, 13

    View full-size slide

  10. OSS
    Saturday, September 21, 13

    View full-size slide

  11. Saturday, September 21, 13

    View full-size slide

  12. Kiwi
    Saturday, September 21, 13

    View full-size slide

  13. Kiwi
    Saturday, September 21, 13

    View full-size slide

  14. Alcatraz
    Saturday, September 21, 13

    View full-size slide

  15. Saturday, September 21, 13

    View full-size slide

  16. The point
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  29. Defaults out of the
    box
    tweaking when you need it
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  33. ObjectiveSugar
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  35. 5.times {
    puts "hello!"
    }
    for (int i = 0; i < 5; i++ ) {
    NSLog(@"Hello");
    }
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  37. [@5 times:^{
    NSLog(@"Hello!");
    }];
    [@1 upto:5 do:^(int number) {
    NSLog(@"The number is: %d", number);
    }];
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  41. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts {
    }
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  46. - (NSArray *)createPeopleFromDictionaries:(NSArray *)peopleInDicts {
    }
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  53. NSArray
    - lastObject
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  55. Strings
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  62. unless
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  65. NSDate
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  71. CoreData
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  73. ObjectiveRecord
    Saturday, September 21, 13

    View full-size slide

  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

    View full-size slide

  75. AppDelegate
    Saturday, September 21, 13

    View full-size slide

  76. AppDelegate
    160 loc
    Saturday, September 21, 13

    View full-size slide

  77. CoreData
    • creating
    • fetching
    • modifying
    • saving / deleting
    Saturday, September 21, 13

    View full-size slide

  78. Creating
    Saturday, September 21, 13

    View full-size slide

  79. Saturday, September 21, 13

    View full-size slide

  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

    View full-size slide

  81. NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    Event *event = [Event create:@{ @"timeStamp": [NSDate date] } inContext:context];
    [event save];
    Saturday, September 21, 13

    View full-size slide

  82. Fetching
    Saturday, September 21, 13

    View full-size slide

  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

    View full-size slide

  84. [Person all];
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  88. BYOMOC™
    Saturday, September 21, 13

    View full-size slide

  89. Testing
    Saturday, September 21, 13

    View full-size slide

  90. Domain Logic Persistence
    Saturday, September 21, 13

    View full-size slide

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

    View full-size slide

  92. Mapping
    Saturday, September 21, 13

    View full-size slide

  93. @interface Person : NSManagedObject
    @property(strong, nonatomic) NSString *firstName;
    @property(strong, nonatomic) NSString *lastName;
    @property(strong, nonatomic) NSNumber *age;
    @end
    Saturday, September 21, 13

    View full-size slide

  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

    View full-size slide

  95. CoreData 3 NSNull
    Saturday, September 21, 13

    View full-size slide

  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

    View full-size slide

  97. Thanks
    Saturday, September 21, 13

    View full-size slide