I have a view controller that shows two tableView
s side by side.
I have also a class (ButtonHeaderFooterView
) that extends from UITableViewHeaderFooterView
.
I want to show different titles for the header depending on the table view, but it's not working for me.
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet private var leftTableView: UITableView!
@IBOutlet private var rightTableView: UITableView!
private var cachedHeader: ButtonHeaderFooterView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
ButtonHeaderFooterView.register(forTable: leftTableView)
ButtonHeaderFooterView.register(forTable: rightTableView)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if tableView == leftTableView {
return ""
}
return ""
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let cachedHeader = cachedHeader {
return cachedHeader
}
guard let headerView = ButtonHeaderFooterView.dequeue(forTable: tableView) else {
fatalError("Failed to dequeue header/footer view buttonHeaderFooterView")
}
cachedHeader = headerView
return headerView
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
guard let header = view as? ButtonHeaderFooterView else {
return
}
if tableView == leftTableView {
header.textLabel?.text = "Test 1"
} else {
header.textLabel?.text = "Test 2"
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 36
}
}
ButtonHeaderFooterView.swift
import Foundation
import UIKit
protocol ButtonHeaderFooterDelegate: AnyObject {
func buttonTapped()
}
class ButtonHeaderFooterView: UITableViewHeaderFooterView {
static let identifier = "ButtonHeaderFooterView"
@IBOutlet private var titleLabel: UILabel!
static func dequeue(forTable tableView: UITableView) -> ButtonHeaderFooterView? {
tableView.dequeueReusableHeaderFooterView(withIdentifier: ButtonHeaderFooterView.identifier) as? ButtonHeaderFooterView
}
static func register(forTable tableView: UITableView) {
tableView.register(UINib(nibName: "ButtonHeaderFooterView", bundle: nil), forHeaderFooterViewReuseIdentifier: ButtonHeaderFooterView.identifier)
}
}
Here's a screenshot of what I see.
Do you know what I'm doing wrong?
I think the problem may be related to the cachedHeader
ivar. I think it needs to be removed along side with:
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
, andfunc tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
method.You can set the string right after dequeuing the header view.
Probably something along the lines of will be a better bet:
import UIKit
class ViewController: UIViewController {
@IBOutlet private var leftTableView: UITableView!
@IBOutlet private var rightTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
ButtonHeaderFooterView.register(forTable: leftTableView)
ButtonHeaderFooterView.register(forTable: rightTableView)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let headerView = ButtonHeaderFooterView.dequeue(forTable: tableView) else {
fatalError("Failed to dequeue header/footer view buttonHeaderFooterView")
}
if tableView == leftTableView {
headerView.textLabel?.text = "Test 1"
} else {
headerView.textLabel?.text = "Test 2"
}
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 36
}
}
There is not need to cache the header view as the table view will do it for you. This is why you need to dequeue the header view in the first place.