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

The Evolution of a Cocoa Programmer

The Evolution of a Cocoa Programmer

Chris Eidhof | @chriseidhof

January 11, 2014
Tweet

More Decks by Chris Eidhof | @chriseidhof

Other Decks in Technology

Transcript

  1. Example code @interface HiscoreTableViewCell : UITableViewCell { IBOutlet UIImageView *badge;

    IBOutlet UILabel *badgeTitle; IBOutlet UILabel *name1; IBOutlet UILabel *name2; IBOutlet UILabel *name3; IBOutlet UILabel *position1; IBOutlet UILabel *position2; IBOutlet UILabel *position3; IBOutlet UILabel *score1; IBOutlet UILabel *score2; IBOutlet UILabel *score3; }
  2. Example code (continued) @property (nonatomic,readonly) UIImageView* badge; @property (nonatomic,readonly) UILabel

    *badgeTitle; @property (nonatomic,readonly) UILabel *name1; @property (nonatomic,readonly) UILabel *name2; @property (nonatomic,readonly) UILabel *name3; @property (nonatomic,readonly) UILabel *position1; @property (nonatomic,readonly) UILabel *position2; @property (nonatomic,readonly) UILabel *position3; @property (nonatomic,readonly) UILabel *score1;
  3. Example code (continued) @synthesize badge; @synthesize badgeTitle; @synthesize name1; @synthesize

    name2; @synthesize name3; @synthesize position1; @synthesize position2; @synthesize position3; @synthesize score1; @synthesize score2; @synthesize score3;
  4. //TODO: as of here, it is completely broken if ([gameView

    superview] != nil) { [[SoundBoard sharedSoundBoard] startMenuTune]; [menuViewController viewWillAppear:YES]; [gameViewController viewWillDisappear:YES]; [gameView removeFromSuperview]; [gameViewController viewDidDisappear:YES]; [menuViewController viewDidAppear:YES]; } else {
  5. NSURL *cgiUrl = [NSURL URLWithString:POST_SCORE_URL]; NSMutableURLRequest *p = [NSMutableURLRequest requestWithURL:cgiUrl];

    [p setTimeoutInterval:4]; [p setHTTPMethod:@"POST"]; [p setHTTPBody:requestData]; NSURLResponse *response = nil; NSError *error = nil; NSData *responseData = [NSURLConnection sendSynchronousRequest:p returningResponse:&response error:&error];
  6. 2014 1986 1988 1990 1992 1994 1996 1998 2000 2002

    2004 2006 2008 2010 2012 1 2 3 4 5 Time How much I know
  7. 2014 1986 1988 1990 1992 1994 1996 1998 2000 2002

    2004 2006 2008 2010 2012 1 2 3 4 5 Time How much I know
  8. I used to do this: if (buttonIndex == 0) instead,

    now I write if (buttonIndex == StartButton)
  9. I used to write this: if ([game state] == running

    || self.trainingMode) Now I write this: BOOL shouldPauseGame = game.state == running || self.trainingMode; if (shouldPauseGame)
  10. Write small files 325 ./THStyleSheet.m 279 THSkillboxView.m 263 THCardsViewController.m 243

    THTimeLineView.m 221 THScreeningBarViewController.m 192 THEditPriorityViewController.m 185 User+Extensions.m 183 THScreenInstanceViewController.m 183 THRootViewController.m 179 THUserScreenInstancesController.m 168 THPriorityTimelineCollectionController.m 155 UIView+Extensions.m 155 NSArray+Extensions.m 154 THZoomingNavigationController.m
  11. Deep code paths - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if (alertState

    == submitScore && game.score > 0) { // 20 lines if (result != nil && [resultKeys containsObject:@"position"] && [resultKeys containsObject:@"neededPoints"] && [resultKeys containsObject:@"deviceHighscore"] && [resultKeys
  12. What prevents me from using Core Data at this point

    is my concern for scalability and performance. It’s possible I’m just being thick-headed. — Brent Simmons, 27 Sep 2013
  13. So last weekend I switched from SQLite/FMDB to Core Data.

    This may come as a surprise. — Brent Simmons, 05 Oct 2013
  14. I used NSDictionary for everything NSDate* birthDate = [NSDate dateWithTimeIntervalSince1970:131855*3600];

    NSDictionary* person = @{ @"name": @"Chris", @"birthdate": birthDate, @"numberOfKids": @0 };
  15. A first step @interface Person : NSObject @property (nonatomic,copy) NSString*

    name; @property (nonatomic) NSDate* birthDate; @property (nonatomic) NSUInteger numberOfKids; @end
  16. @interface Person : NSObject @property (nonatomic,readonly) NSString* name; @property (nonatomic,readonly)

    NSDate* birthDate; @property (nonatomic,readonly) NSUInteger numberOfKids; - (instancetype) initWithName:(NSString*)name birthDate:(NSDate*)birthDate numberOfKids:(NSUInteger)numberOfKids; @end
  17. What can you do? —Smarter views —Smarter models —Use view

    controller transitions —Use categories to populate views —Pull out protocols
  18. Use categories to populate views - (UITableViewCell*)tableView:(UITableView*)tv cellForRowAtIndexPath:(NSIndexPath*)ip { User

    *user = [self userAtIndexPath:ip]; MyCell *cell = [tv dequeueReusableCellWithIdentifier:ruI forIndexPath:ip]; cell.textLabel.text = user.name; cell.imageView.image = user.avatar; .... }
  19. Use categories to populate views —Your view controller is a

    bit simpler —Your population code can be reused ... —But now your view knows about your model. Sort of.
  20. Creating a separate data source object - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)sectionIndex {

    id<NSFetchedResultsSectionInfo> section; section = self.frc.sections[sectionIndex]; return section.numberOfObjects; }
  21. Creating a separate data source object Working with the delegate

    - (UITableViewCell*)tableView:(UITableView*)tv cellForRowAtIndexPath:(NSIndexPath*)ip { id object = [self objectAtIndexPath:indexPath]; id cell = [tv dequeueReusableCellWithIdentifier:ruI forIndexPath:ip]; [self.delegate configureCell:cell withObject:object]; return cell; }
  22. Advantages of a separate data source —Lighter view controller —Testable

    —Reusable And you can do this for other protocols, too