Swift Quick Fix: UITableViewController

This is the first in a series of what I am calling a "Swift Quick Fix". Things we know how to do very well in Objective-C, but might need a quick hint on how to do it in Swift.

Like implementing a UITableViewController in Objective-C, we have to implement a minimum of 3 of the methods defined in the UITableViewController protocol.

numberOfSectionsInTableView  
tableView:numberOfRowsInSection  
tableView:cellForRowAtIndexPath  

We'll take this one at a time. First, numberOfSectionsInTableView.

Implemented in Objective-C, this should look pretty familiar:

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

The same thing in Swift looks like this:

override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {  
    return 1
}

Different, yet still familiar. The only things the will look weird at first are the use of override and func, and the way the return type is defined (that -> Int bit.) These will all become second nature pretty quickly. Also notice, no ;. Yay!

Implementing tableView:numberOfRowsInSection is only marginally more complex. Let's say we have an NSArray that contains a list of colors of the rainbow. (Red, Orange, Yellow, Green, Blue, Indigo, Violet).

Your Objective-C implementation might look like this:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.rainbowColors.count;
}

The Swift equivalent would look like this:

override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {  
    return self.rainbowColors.count
}

Almost the exact same code! Cool!

So how does that array get initialized?

In Objective-C you would have probably created a property to hold the array, and then initialized the array in your class's init method, like this:

// MyTableViewController.h
...
@property(nonatomic, strong) NSArray* rainbowColors;

// MyTableViewController.m
...
- (id) init {
    self = [super init];
    if (self) {
        self.rainbowColors = [[NSArray alloc] initWithObjects:@"Red", @"Orange", @"Yellow", @"Green", @"Blue", @"Indigo", @"Violet", nil];
    }
    return self;
}

This is about the time you start to appreciate Swift's brevity. Here's the same thing in Swift.

// MyTableViewController.swift
let rainbowColors = ["Red","Orange","Yellow", "Green", "Blue", "Indigo", "Violet"]  

This syntax should be familiar if you have used just about any programming language.

Next we'll look at actually building the cell to be displayed, using the tableView:cellForRowAtIndexPath method. In Objective-C, we would do something similar to this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"ColorCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [self.rainbowColors objectAtIndex: [indexPath row]];
    return cell;
}

The same thing in Swift:

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {  
    let reuseIndentifier = "ColorCell"

    var cell:UITableViewCell? = tableView?.dequeueReusableCellWithIdentifier(reuseIndentifier) as? UITableViewCell

    if !cell {
        cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIndentifier)
    }

    cell!.textLabel.text = self.rainbowColors[indexPath.row]

    return cell
}

This is pretty straight forward, but the question marks in there might be a bit confusing. What are those about? This is part of what is called "optional chaining" On the left side of the equals sign, the var cell:UITableViewCell? basically says "If everything to the right of the equal sign has a value, set cell equal to that value, otherwise set it to nil" On the right of the equal sign, the tableView?.dequeueReusableCellWithIdentifier(reuseIndentifier) as? UITableViewCell basically says "If tableView is not nil, and we can get a cell with the specified reuse identifier, return that, otherwise return nil". Pretty nifty.