Tamas
Tamas

Reputation: 3442

setup custom UITableViewHeaderFooterView for reusability

I have a custom section header view defined and registered like this:

class MySectionHeaderView : UITableViewHeaderFooterView {
    var section : Int?
    var button : UIButton?
}

class MyTableViewController : UITableViewController {

    override func loadView() {
        super.loadView()
        self.tableView.register(MySectionHeaderView.self,
            forHeaderFooterViewReuseIdentifier: "reuseIdentifier")
    }

    override func tableView(_ tableView: UITableView,
            viewForHeaderInSection section: Int) -> UIView? {
        let header = tableView.dequeueReusableHeaderFooterView(
            withIdentifier: "reuseIdentifier")! as! MySectionHeaderView
        header.textLabel?.text = titleForHeader(section: section)
        header.section = section
        if header.button == nil {
           let button = UIButton(type: .system)
           // ... configure button ... //
           header.button = button
        }
        return header
    }
}

This works. However it is very strange to put the button and other intializers inside the function tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView. as it breaks the separation of concerns principile. This functions should be about only to set the labels, etc.

Is there a way to initialize the header view, creating sub elements somewhere inside the class MySectionHeaderView?

Upvotes: 1

Views: 2816

Answers (1)

Rakesha Shastri
Rakesha Shastri

Reputation: 11243

Set only the data source dependent information of your header in viewForHeaderInSection. Move all the setup code inside the custom header class.

class MySectionHeaderView: UITableViewHeaderFooterView {
    var section: Int?
    lazy var button: UIButton = {
        let button = UIButton(type: .system)
           // ... configure button ... //
        return button
    }()

    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)

        //Add subviews and set up constraints
    }
}

Now in your delegate method,

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = tableView.dequeueReusableHeaderFooterView(
        withIdentifier: "reuseIdentifier")! as! MySectionHeaderView
    header.textLabel?.text = titleForHeader(section: section)
    header.section = section
    return header
}

Upvotes: 2

Related Questions