Outsource your UITableViewDataSource!
It is very common that the controller of an UITableView is also its data source. This is the number one reason why view controllers tend to become very massive. Outsourcing the data source to an object on its own is a better solution.
Hint: This post has been updated to Swift 3 and Xcode 8.
Let’s take a look at an example:
import UIKit class TableViewController: UITableViewController { private var movies = [String]() //MARK: - UIViewController override func viewDidLoad() { movies = ["Terminator","Back To The Future","The Dark Knight"] tableView.reloadData() } //MARK: - UITableViewDataSource override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return movies.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")! cell.textLabel?.text = movies[indexPath.row] return cell } }
The table view displays three cells containing movie titles. Nevertheless you can see in this simple example that there is already a lot of code in the view controller. If you add all the other stuff a view controller needs to do, it will become massive quickly.
So there is a better solution. We create a class called DataSource and move all the data source methods to that class:
import UIKit class DataSource: NSObject, UITableViewDataSource { var movies = [String]() //MARK: - UITableViewDataSource func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return movies.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")! cell.textLabel?.text = movies[indexPath.row] return cell } }
Now, TableViewController just needs to create an instance of this object and set it as the table view’s data source:
import UIKit class TableViewController: UITableViewController { private let dataSource = DataSource() //MARK: - UITableViewDataSource override func viewDidLoad() { dataSource.movies = ["Terminator","Back To The Future","The Dark Knight"] tableView.dataSource = dataSource } }
The view controller is cleaned up now!
More generally, this method works not only with table views but with all views that need a data source, like UICollectionView or a view you have written on your own.
Video
Resources:
Title Image: @ enzozo / shutterstock.com