Sunday, February 17, 2019

Add a header for UITableView

I'm developing a pet project, MyCalculator. I'm using a tableview to display the history of Math operations the user has entered. The image below shows how it looks like. (Note that I'm using Xcode 9 and Swift 3 to write this post.) 



At first, I dragged a UILabel and dropped it on the UITableView above the UITableViewCell in the Interface Builder. When I run the app, the label is on top of all cells so it looked like a header. But, when I started scrolling down the tableview, the label moved up along with the cells and disappeared. This is not right. The header is supposed to be fixed on top. Then, I figured that the correct way of adding a header for the tableview is overriding the UITableViewDelegate's method:

tableView(_:UITableView, viewForHeaderInSection:Int) -> UIView?

In this post, I'm gonna create the header view using a XIB file. Some people might create it programmatically.

1. Overriding the UITableViewDelegate's tableView() method


Make sure the ViewController conform to UITableViewDelegate protocol and then override the method as following:

public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return historyPopup?.dequeueReusableHeaderFooterView(withIdentifier: "HistoryTableViewHeader") as! HistoryTableViewHeader
}
 

HistoryTableViewHeader is a customer class I created in the step below. As the header view will be created using a xib file, we have to register it in the ViewController's viewDidLoad() method as following:

historyPopup?.register(UINib(nibName: "HistoryTableViewHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: "HistoryTableViewHeader")
 

2. Creating HistoryTableViewHeader.swift File


import Foundation
import UIKit

public class HistoryTableViewHeader : UITableViewHeaderFooterView {
    
}
 

3. Creating HistoryTableViewHeader.xib File


a). Select File > New > File... then select View under the User Interface section and click Next. When a dialog shows up, name the file as HistoryTableViewHeader.xib and click Create.

b). find the file in the Project Navigator and open it. Then, drag a UIView from the Object Library and drop it on the view xib, and set appropriate constraints to make the UIView as a container or background view. After that, add a (History) UILabel to the container view and set any constraints needed.


c). make sure the Square icon is selected then open the Identity Inspector and set Class property under Custom Class section to HistoryTableViewHeader.

d). make sure the cube or File's Owner icon is selected then open the Identity Inspector and set Class property under Customer Class section to HistoryTableViewHeader.

e). Control-drag the History label to HistoryTableViewHeader class to create an outlet so that the label is accessible from the ViewController or other classes. When a popup appears, set Name to label and change Object from File's Owner to History Table View Header as shown in the image below (the option shows up in the listbox because of step c above).



Note that setting Object to File's Owner caused the run-time exception:
    
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key xib
 


No comments:

Post a Comment