View Controller Extensions

Edited (6/24/18): This story was imported from my old personal blog. Apologies ahead of time for wonky code blocks. Also I’ve learned an enormous amount since then, including that this usually isn’t a great strategy for code separation. For historical purposes I’m leaving it here though.

Say you are trying to make an iOS app that uses a UITableView. Along with the code that provides custom functionality, your view controller will need to conform to the UITableView data source and delegate in order to access methods that bring your views to life. This means including all of the protocol methods in your view controller.

// DataSource 
func numberOfSectionsInTableView(tableview: UITableView) -> Int { return 1 // This will reflect the sections you need
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
return Data.dataStore.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let row = indexPath.row cell.textLabel?.text = Data.dataStore[row] return cell
}
// Delegate 
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let row = indexPath.row print(Data.dataStore[row])
}

Phew…there’s a lot of code that’s really just there to conform to the protocols! Of course you can always just use some //colorful comments or MARK in order to add visual separation from the rest of your code. However that doesn't follow the "single responsibility" paradigm, and it clutters up the code base. What if there was a way to just move all of that code into its own file? Good news everyone, there is! All we need are some handy extensions.

Welcome to the Extension Zone

Extensions allow you to…wait for it…extend the functionality of a class, structure, enumeration, or protocol type. Say you wanted to add a custom method to the NSString class. Extensions let you do that. Or maybe you want to separate out some code, say in a view controller, into a different file. Extensions let you do that! Just take the code from before and bring it out into it’s own file. This is demonstrated as follows.

ViewController+DataSource.swift

extension ViewController: UITableViewDataSource { 
func numberOfSectionsInTableView(tableview: UITableView) -> Int { 
return 1 // This will reflect the sections you need
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
return Data.dataStore.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let row = indexPath.row cell.textLabel?.text = Data.dataStore[row] return cell
}
}

ViewController+Delegate.swift

extension ViewController: UITableViewDelegate { 
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
let row = indexPath.row print(Data.dataStore[row])
}
}

Voila. Now all of the code related to the DataSource and Delegate protocols are contained within their own files. These methods are isolated from the rest of your view controller, yet they still provide the essential capabilities to your program.

One thing to make sure of though is that the delegate and data source for your tableview is assigned correctly. The easiest way to do this is through Interface Builder with the ctrl+drag functionality. Select the tableview and connect it to the parent ViewController for both data source and delegate, like so...

Now you’re all set. Sporting a sleek, slimmed down VC!


Originally published at blog.alexpersian.com on September 24, 2015.