All about TableViews

Sept 19, 2017   3 minutes to read



Part 1: Listing Elements

1
First we create a new "Single-View App" Project in Xcode (Shortcut: + + N).

2
Next, we select the "Main.storyboard" from the Project Navigator and Drag a Table-View from the "Object Library" into the ViewController View. We stretch our TableView such that it fills our ViewController View.

Fig. 1Screencast of the Object Library window. Where we can drag the Table View from.



3
We Ctrl-Drag the Table View over the yellow-Circle (representing the ViewController), and release it. From the options that will pop-up (Figure. 2), we select the "delegate" and "dataSource" option. As a result our ViewController is now connected to the TableView as the Delegate and Datasource of the TableView.

Fig. 2Screencast of the Storyboard, where we create the relation between our TableView and the ViewController.



4
Inside the "ViewController.swift" file, we need to modify the Class inheritance from:
class ViewController: UIViewController {
    ...
}
to
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    ...
}

In order to inherit from "UITableViewDataSource" we have to conform to the UITableViewDataSource-Protocol. Which requires us to at least provide two functions. Since long functions are hard to remember, it comes handy that Xcode will auto-complete (Figure 3) each one, after just typing the keywords listed below.
 numberOfRowsInSection 
 cellForRowAt 
Depending on wether our TableView has multiple sections or not (Default = 1 Section), we might consider the following function as well:
 numberOfSection 

Fig. 3Screencast of Xcode, autocompleting the function "numberOfRowsInSection".



5
Before we modify the previously created two functions, we should create an Array of strings, that we want to populate our TableView with:
var data = ["John", "Carl", "Kenny"]

Now we can go into the function "numberOfRowsInSection", which requires us to return the number of rows that our table has in a Section (Notice: We have only 1 section as default). In this case, we want the number of rows to be equivalent to the number of Strings our data array contains. Therefore, we modify the function as follows:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return data.count
}

6
In order to implement the "cellForRowAt" function, we need to make some adjustments. First, we do not want to create a new Cell for each entry, since this can be a huge overhead for large amount of data. Instead we want to "dequeue" and reuse our Cells if necessary. The idea is that we only create a few number of Cells, necessary to fill the complete view (e.g iPhone Display height). And everytime we drag a Cell out of the view to show the next cell, we DO NOT create a new Cell, but instead reuse pre-existing Cells by "dequeueing" and reusing it.

To use this dequeueing technique, we go back to our storyboard. Inside the TableViews "Attributes Inspector" we set the "Content" as "Dynamic Prototypes" and the "Prototype Cells" to "1". A new Cell is now displayed in our TableView. Now we have to provide our Cell an Identifier, which we will use to refer to our Prototype Cell in our code later. For this we simply select the newly created Cell and inside the "Attributes Inspector" we set the Identifier as "Cell" (Figure 4).

Fig. 4Screencast of how a Prototype Cell is created and assigned an Identifier.



7
Now that we have our Prototype Cell set up, we can switch back to our "ViewController.swift" file and adjust the "cellForRowAt" function as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

  let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
  cell.textLabel?.text = data[indexPath.row]
  
  return cell
}   


8
When we run our Simulator (shortcut: + R ), we should now see our TableView populated with the names we previously stored in our data Array.

Final Source Code:

//
//  ViewController.swift
//
import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    var data = ["John", "Carl", "Kenny"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier:
        "Cell", for: indexPath)
        cell.textLabel?.text = data[indexPath.row]
        
        return cell
    }
}