Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

@mneorr mneorr.com Saturday, September 21, 13

Slide 3

Slide 3 text

Rijeka (Fiume) Saturday, September 21, 13

Slide 4

Slide 4 text

PROGRAMMERS Saturday, September 21, 13

Slide 5

Slide 5 text

PROGRAMMERS Cat people Saturday, September 21, 13

Slide 6

Slide 6 text

PROGRAMMERS Cat people Dog people Saturday, September 21, 13

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Đuro Saturday, September 21, 13

Slide 9

Slide 9 text

Saturday, September 21, 13

Slide 10

Slide 10 text

OSS Saturday, September 21, 13

Slide 11

Slide 11 text

Saturday, September 21, 13

Slide 12

Slide 12 text

Kiwi Saturday, September 21, 13

Slide 13

Slide 13 text

Kiwi Saturday, September 21, 13

Slide 14

Slide 14 text

Alcatraz Saturday, September 21, 13

Slide 15

Slide 15 text

Saturday, September 21, 13

Slide 16

Slide 16 text

The point Saturday, September 21, 13

Slide 17

Slide 17 text

shorter != better Saturday, September 21, 13

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

• 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

Slide 20

Slide 20 text

- (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

Slide 21

Slide 21 text

- (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

Slide 22

Slide 22 text

- (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

Slide 23

Slide 23 text

- (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

Slide 24

Slide 24 text

- (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

Slide 25

Slide 25 text

- (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

Slide 26

Slide 26 text

- (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

Slide 27

Slide 27 text

- (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

Slide 28

Slide 28 text

- (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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

ObjectiveSugar Saturday, September 21, 13

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

- (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

Slide 45

Slide 45 text

- (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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

NSArray - lastObject Saturday, September 21, 13

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

Strings Saturday, September 21, 13

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

unless Saturday, September 21, 13

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

NSDate Saturday, September 21, 13

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

CoreData Saturday, September 21, 13

Slide 72

Slide 72 text

CoreData 3 talks so far Saturday, September 21, 13

Slide 73

Slide 73 text

ObjectiveRecord Saturday, September 21, 13

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

AppDelegate Saturday, September 21, 13

Slide 76

Slide 76 text

AppDelegate 160 loc Saturday, September 21, 13

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Creating Saturday, September 21, 13

Slide 79

Slide 79 text

Saturday, September 21, 13

Slide 80

Slide 80 text

- (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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

Fetching Saturday, September 21, 13

Slide 83

Slide 83 text

• 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

Slide 84

Slide 84 text

[Person all]; Saturday, September 21, 13

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

BYOMOC™ Saturday, September 21, 13

Slide 89

Slide 89 text

Testing Saturday, September 21, 13

Slide 90

Slide 90 text

Domain Logic Persistence Saturday, September 21, 13

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

Mapping Saturday, September 21, 13

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

{ "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

Slide 95

Slide 95 text

CoreData 3 NSNull Saturday, September 21, 13

Slide 96

Slide 96 text

• - 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

Slide 97

Slide 97 text

Thanks Saturday, September 21, 13