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

Lighter View Controllers

Lighter View Controllers

Slides of the talk I gave at NSSpain. Probably makes more sense with the video, or read the articles: http://www.objc.io/issue-1/

Ade0c334ecff1448bb96f5f733bf1f83?s=128

Chris Eidhof | @chriseidhof

September 19, 2013
Tweet

Transcript

  1. Lighter View Controllers Chris Eidhof NSSpain 2013 Wednesday, September 18,

    13
  2. What’s the largest file in your project? Wednesday, September 18,

    13
  3. What’s the largest file in your project? 0 200 400

    600 800 Wednesday, September 18, 13
  4. (image by Manu Cornet) Wednesday, September 18, 13

  5. (image by Manu Cornet) Wednesday, September 18, 13

  6. View controllers are the non-reusable part of your project Wednesday,

    September 18, 13
  7. find . -name "*.m" -exec wc -l "{}" \; |

    sort -n Wednesday, September 18, 13
  8. 154 ./ViewControllers/THUserPrioritiesViewController.m 154 ./ViewControllers/THZoomingNavigationController.m 155 ./Extensions/NSArray+Extensions.m 155 ./Extensions/UIView+Extensions.m 168 ./Controllers/THPriorityTimelineCollectionController.m

    179 ./Controllers/THUserScreenInstancesController.m 183 ./ViewControllers/THRootViewController.m 183 ./ViewControllers/THScreenInstanceViewController.m 185 ./Model/User+Extensions.m 192 ./ViewControllers/THEditPriorityViewController.m 221 ./ViewControllers/THScreeningBarViewController.m 243 ./Views/THTimeLineView.m 263 ./ViewControllers/THCardsViewController.m 279 ./Views/THSkillboxView.m 325 ./THStyleSheet.m Wednesday, September 18, 13
  9. 154 ./ViewControllers/THUserPrioritiesViewController.m 154 ./ViewControllers/THZoomingNavigationController.m 155 ./Extensions/NSArray+Extensions.m 155 ./Extensions/UIView+Extensions.m 168 ./Controllers/THPriorityTimelineCollectionController.m

    179 ./Controllers/THUserScreenInstancesController.m 183 ./ViewControllers/THRootViewController.m 183 ./ViewControllers/THScreenInstanceViewController.m 185 ./Model/User+Extensions.m 192 ./ViewControllers/THEditPriorityViewController.m 221 ./ViewControllers/THScreeningBarViewController.m 243 ./Views/THTimeLineView.m 263 ./ViewControllers/THCardsViewController.m 279 ./Views/THSkillboxView.m 325 ./THStyleSheet.m Wednesday, September 18, 13
  10. ... but this view controller is important! Wednesday, September 18,

    13
  11. Steps Project: A complete OS in <20K lines Wednesday, September

    18, 13
  12. What can we do? Wednesday, September 18, 13

  13. Wednesday, September 18, 13

  14. A view controller intermediates between model and view Wednesday, September

    18, 13
  15. Model logic Wednesday, September 18, 13

  16. View Logic Wednesday, September 18, 13

  17. View Layout Wednesday, September 18, 13

  18. Webservice Wednesday, September 18, 13

  19. View Controller View Child View Controller Model Webservice Wednesday, September

    18, 13
  20. Demo Wednesday, September 18, 13

  21. View Controller View Child View Controller Model Webservice Wednesday, September

    18, 13
  22. View Controller View Child View Controller Model Webservice Wednesday, September

    18, 13
  23. Model Logic Move into model subclass or into a separate

    class Wednesday, September 18, 13
  24. Some Stats 18 ./NestedTodoList/main.m 30 ./Item.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m

    52 ./NestedTodoList/AppDelegate.m 255 ./NestedTodoList/ItemViewController.m Wednesday, September 18, 13
  25. What does it do? ‣ View Setup ‣ Table View

    Delegate ‣ Table View Datasource ‣ Fetched Results Controller Delegate ‣ Adding items ‣ Deleting Items ‣ ... Wednesday, September 18, 13
  26. Custom Datasource What does it do? ‣ View Setup ‣

    Table View Delegate ‣ Table View Datasource ‣ Fetched Results Controller Delegate ‣ Adding items ‣ Deleting Items ‣ ... Wednesday, September 18, 13
  27. Custom Datasource Model What does it do? ‣ View Setup

    ‣ Table View Delegate ‣ Table View Datasource ‣ Fetched Results Controller Delegate ‣ Adding items ‣ Deleting Items ‣ ... Wednesday, September 18, 13
  28. Model - (BOOL)textFieldShouldReturn:(UITextField*)t { NSString* title = t.text; NSUInteger order

    = self.parent.children.count; Item* item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:self.moc]; item.title = title; item.parent = self.parent; item.order = @(order); ... } Wednesday, September 18, 13
  29. Model - (BOOL)textFieldShouldReturn:(UITextField*)t { NSString* title = t.text; [Item insertItemWithTitle:title

    parent:self.parent inManagedObjectContext:self.moc]; ... } Wednesday, September 18, 13
  30. - (void)deleteItem:(id)object { Item* item = object; NSSet* siblings =

    item.parent.children; NSPredicate* predicate = [NSPredicate pre NSSet* itemsAfterSelf = [siblings filtere [itemsAfterSelf enumerateObjectsUsingBloc { sibling.order = @(sibling.order.integ }]; [item.moc deleteObject:item]; } Wednesday, September 18, 13
  31. - (void)deleteItem:(id)object { Item* item = object; NSSet* siblings =

    item.parent.children; NSPredicate* predicate = [NSPredicate pre NSSet* itemsAfterSelf = [siblings filtere [itemsAfterSelf enumerateObjectsUsingBloc { sibling.order = @(sibling.order.integ }]; [item.moc deleteObject:item]; } Wednesday, September 18, 13
  32. - (void)prepareForDeletion { NSSet* siblings = self.parent.children; NSPredicate* p =

    [NSPredicate predicateWithFormat:@"order > %@", self.order]; NSSet* itemsAfterSelf = [siblings filteredSetUsingPredicate:p]; [itemsAfterSelf enumerateObjectsUsingBlock: ^(Item* sibling, BOOL* stop) { sibling.order = @(sibling.order.integerValue - 1); }]; } Wednesday, September 18, 13
  33. Some Stats 18 ./NestedTodoList/main.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m

    54 ./Item.m 241 ./NestedTodoList/ItemViewController.m Wednesday, September 18, 13
  34. Wednesday, September 18, 13

  35. View Controller View Child View Controller Model Webservice UITableViewDS Wednesday,

    September 18, 13
  36. View Controller View Child View Controller Model Webservice UITableViewDS Wednesday,

    September 18, 13
  37. @interface FetchedResultsControllerDataSource : NSObject <UITableViewDataSource, NSFetchedResultsControllerDelegate> Wednesday, September 18, 13

  38. #pragma mark UITableViewDatasource Wednesday, September 18, 13

  39. - (NSInteger)numberOfSectionsInTableView:(UITableView*)t { return self.fetchedResultsController.sections.count; } Wednesday, September 18, 13

  40. - (NSInteger)tableView:(UITableView*)t numberOfRowsInSection:(NSInteger)s { id<NSFetchedResultsSectionInfo> section = self.fetchedResultsController.sections[s]; return section.numberOfObjects;

    } Wednesday, September 18, 13
  41. - (UITableViewCell*)tableView:(UITableView*)t cellForRowAtIndexPath:(NSIndexPath*)ip Wednesday, September 18, 13

  42. #pragma mark NSFetchedResultsControllerDelegate Wednesday, September 18, 13

  43. - (void)controller:(NSFetchedResultsController*)c didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)ct newIndexPath:(NSIndexPath*)newIndexPath Wednesday, September 18, 13

  44. @property (nonatomic, weak) id <FRCDataSourceDelegate> delegate; Wednesday, September 18, 13

  45. - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { id object = [self.frc objectAtIndexPath:indexPath]; id

    cell = [tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier forIndexPath:indexPath]; [self.delegate configureCell:cell withObject:object]; return cell; } Wednesday, September 18, 13
  46. - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { id object = [self.frc objectAtIndexPath:indexPath]; id

    cell = [tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier forIndexPath:indexPath]; [self.delegate configureCell:cell withObject:object]; return cell; } Wednesday, September 18, 13
  47. Some Stats (3) 25 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m 64

    ./Item.m 111 ./NestedTodoList/FRCDataSource.m 162 ./NestedTodoList/ItemViewController.m Wednesday, September 18, 13
  48. Code re-use ☺ Wednesday, September 18, 13

  49. Other Candidates UICollectionViewDataSource UIPageViewControllerDataSource UIPickerViewDataSource Wednesday, September 18, 13

  50. More candidates UICollectionViewDelegate UIScrollViewDelegate UITableViewDelegate UITableViewDelegate UITextFieldDelegate Wednesday, September 18,

    13
  51. ... or use a super class? Wednesday, September 18, 13

  52. Superclass disadvantages You only have 1 superclass Harder to switch

    from table view to collection view Easier to make mistakes: e.g. forget to call super methods. Wednesday, September 18, 13
  53. Superclass disadvantages You only have 1 superclass Harder to switch

    from table view to collection view Easier to make mistakes: e.g. forget to call super methods. Wednesday, September 18, 13
  54. Superclass disadvantages You only have 1 superclass Harder to switch

    from table view to collection view Easier to make mistakes: e.g. forget to call super methods. objc_requires_super Wednesday, September 18, 13
  55. Superclass disadvantages You only have 1 superclass Harder to switch

    from table view to collection view Easier to make mistakes: e.g. forget to call super methods. objc_requires_super Wednesday, September 18, 13
  56. View Controller View Child View Controller Model Webservice Wednesday, September

    18, 13
  57. View Controller View Child View Controller Model Webservice Wednesday, September

    18, 13
  58. - (UITableViewCell*)tableView:(UITableView*)t cellForRowAtIndexPath:(NSIndexPath*)ip Wednesday, September 18, 13

  59. // PhotoCell+ConfigureForPhoto.h @interface PhotoCell (ConfigureForPhoto) - (void)configureForPhoto:(Photo *)photo; @end Wednesday,

    September 18, 13
  60. UITableViewController ‣ Clears selection ‣ Reloads data ‣ Flashes scroll

    indicators ‣ Editing ‣ Auto-scrolls to first responder ‣ Refresh control ‣ .... Wednesday, September 18, 13
  61. Wednesday, September 18, 13

  62. Wednesday, September 18, 13

  63. View Controller Containment Wednesday, September 18, 13

  64. Wednesday, September 18, 13

  65. ... or in code [self addChildViewController:sliderController]; [self.view addSubview:sliderController]; [UIView animateWithDuration:0.25

    animations:^{ sliderController.view.alpha = 1; [sliderController didMoveToParentViewController:self]; }]; Wednesday, September 18, 13
  66. Communication Wednesday, September 18, 13

  67. Delegate Blocks KVO Wednesday, September 18, 13

  68. Too much overhead? Wednesday, September 18, 13

  69. Interface Builder Wednesday, September 18, 13

  70. Wednesday, September 18, 13

  71. Wednesday, September 18, 13

  72. Wednesday, September 18, 13

  73. Wednesday, September 18, 13

  74. @interface MyCell : UITableViewCell @property (weak) IBOutlet UISlider *slider; @property

    (weak) IBOutlet UISwitch *switch; @end Wednesday, September 18, 13
  75. Custom objects in your nib Wednesday, September 18, 13

  76. Wednesday, September 18, 13

  77. Wednesday, September 18, 13

  78. Wednesday, September 18, 13

  79. Wednesday, September 18, 13

  80. Wednesday, September 18, 13

  81. Outlets also work Wednesday, September 18, 13

  82. @interface NSObject(UINibLoadingAdditions) - (void)awakeFromNib; @end Wednesday, September 18, 13

  83. Testing Wednesday, September 18, 13

  84. Testing Wednesday, September 18, 13

  85. Testing Wednesday, September 18, 13

  86. Separate data source is easy to test Wednesday, September 18,

    13
  87. Category on cell is easy to test Wednesday, September 18,

    13
  88. View Controllers are hard to test Wednesday, September 18, 13

  89. - (void)testNibLoading; { id mockNavController = [self autoVerifiedMockForClass: [UINavigationController class]];

    PhotosViewController *photosViewController = [[PhotosViewController alloc] init]; id photosViewControllerMock = [self autoVerifiedPartialMockForObject: photosViewController]; [[[photosViewControllerMock stub] andReturn:mockNavController] navigationController]; Wednesday, September 18, 13
  90. Tools Sort files by length Know your libraries Refactor: Use

    XCode 5 AppCode Wednesday, September 18, 13
  91. Tools Pull out data sources Use View Controller Containment Move

    code to models and views Wednesday, September 18, 13
  92. About Me @chriseidhof http://www.objc.io http://www.uikonf.com http://chris.eidhof.nl Wednesday, September 18, 13