iOS Storyboards: Why, When, & How?

Christina Moulton, Teak Mobile Inc.

@ChristinaMltn, christina@teakmobile.com

KW iOS Training

What's a Storyboard?

Segues + Scenes + View Controllers

Why & When?

Pros

Quick flow mock up

Easy to create & see transitions

Gestalt view

Can use multiple storyboards & xibs

Cleaner code, less boilerplate

Make Brian do it ;)

Cons

iOS5+ only

Clutter / screen size

Version control conflicts

Can’t do all transitions / custom views (yet)

Exercise 2: Fruit or Vegetable

Create an app with a tableview

The tableview should have 2 sections: Fruits & Vegetables

Each section should list a few items that are fruits or vegetables

Exercise 2: Fruit or Vegetable (Cont'd)

Create a project (single view app)

Replace UIViewController with UITableViewController (check "Is Initial View Controller")

Set the tableview cell to use a prototype cell with style "Basic" and cell identifier "Cell"

Check that tableview the datasource & delegate IBOutlets are hooked up

Remove the auto-generated ViewController class and add a custom UITableViewController

Exercise 2: Fruit or Vegetable (Cont'd)

Use an NSArray to hold the data for each section

Fill the array with a few strings:

@interface FruitVsVegTableVieController: UITableViewController { 
  NSArray *_vegetables;
  NSArray *_fruits;
} 
@end

- (void)viewDidLoad
{
  [super viewDidLoad];
  _vegetables = @[@"carrot", @"radish", @"beet"];
  _fruits = @[@"apple", @"orange", @"tomato"];
}

Exercise 2: Fruit or Vegetable (Cont'd)

Implement the datasource & delegate methods:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  return 2;
}

- (NSString *)tableView:(UITableView *)tableView
  titleForHeaderInSection:(NSInteger)section
{
  return (section == 0)? @"Vegetables": @"Fruit";
}

- (NSInteger)tableView:(UITableView *)tableView
  numberOfRowsInSection:(NSInteger)section
{
  return (section == 0)? _vegetables.count: _fruits.count;
}

Exercise 2: Fruit or Vegetable (Cont'd)

- (UITableViewCell *)tableView:(UITableView *)tableView 
  cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView 
    dequeueReusableCellWithIdentifier:@"Cell"
    forIndexPath:indexPath];
  if (indexPath.section == 0)
  {
    cell.textLabel.text = _vegetables[indexPath.row];
  }
  else
  {
    cell.textLabel.text = _fruits[indexPath.row];
  }
  return cell;
}

Exercise 2: Fruit or Vegetable (Cont'd)

Challenge: Allow editing

Embed tableview controller in navigation controller

Switch to NSMutableArrays and use mutableCopy

_vegetables = [@[@"carrot", @"radish", @"beet"] mutableCopy];
_fruits = [@[@"apple", @"orange", @"tomato"] mutableCopy];

Uncomment & Implement:

self.navigationItem.rightBarButtonItem = self.editButtonItem;

- (BOOL)tableView:(UITableView *)tableView 
  canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
  return YES;
}

Exercise 2: Fruit or Vegetable (Cont'd)

Delegate methods

- (void)tableView:(UITableView *)tableView
  commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
  forRowAtIndexPath:(NSIndexPath *)indexPath
{
  if (editingStyle == UITableViewCellEditingStyleDelete) {
    if (indexPath.section == 0)
    {
     [_vegetables removeObjectAtIndex:indexPath.row];
    }
    else
    {
      [_fruits removeObjectAtIndex:indexPath.row];
    }
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
  }
}

Exercise 2: Fruit or Vegetable (Cont'd)

- (void)tableView:(UITableView *)tableView 
  moveRowAtIndexPath:(NSIndexPath *)fromIndexPath 
  toIndexPath:(NSIndexPath *)toIndexPath;
{
  NSString * objectToMove;
  if (fromIndexPath.section == 0)
  {
    objectToMove = _vegetables[fromIndexPath.row];
    [_vegetables removeObject:objectToMove];
  }
  else
  {
    objectToMove = _fruits[fromIndexPath.row];
    [_fruits removeObject:objectToMove];
  }
  
  if (toIndexPath.section == 0)
  {
    [_vegetables insertObject:objectToMove atIndex:toIndexPath.row];
  }
  else
  {
    [_fruits insertObject:objectToMove atIndex:toIndexPath.row];
  }
}

Exercise 2: Fruit or Vegetable (Cont'd)

Optional: Block editing some rows

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
  // Return NO if you do not want the item to be re-orderable.
  NSString *selectedFood;
  if (indexPath.section == 0)
  {
    selectedFood = _vegetables[indexPath.row];
  }
  else
  {
    selectedFood = _fruits[indexPath.row];
  }
  
  return ![selectedFood isEqualToString:@"tomato"];
}

UIKit: Bars

Toolbar

Status bar

Navigation bar

Tab bar

Search bar

Images from Apple HIG

UIKit: Content Views

UITableview & UITableviewCell

Simple
Grouped
Cell Styles

Images from Apple HIG

UIKit: Content Views

UICollectionView

Images from Apple HIG

UIKit: Content Views

UIImageView & UIImage


UIWebView


UITextview

UIScrollView

UIPage ViewController

Map Kit: MKMapView

Images from Apple HIG

UIKit: iPad Only Content Views

UIPopoverController (iPad only)

UISplitViewController (iPad only)

Images from Apple HIG

Key Classes: UI: Controls

Activity indicator (spinner)

Picker / Date Picker

Buttons

Label

Progress view

Refresh control

Segmented control

Slider

Stepper

Switch

Text field

Images from Apple HIG

Key Classes: UI: Temporary Views

Alert

Action sheet

Modal view

Images from Apple HIG

Questions?

Christina Moulton, Teak Mobile Inc.

@ChristinaMltn, christina@teakmobile.com

KW iOS Training