Edited at

【iOS】UITableViewのSectionHeaderとSectionFooterをdequeuで使いまわしできるようにする

More than 1 year has passed since last update.


iOS その3 Advent Calendar

3日目も書かせていただきます!

予約投稿最高!

ちなみに前日も書かせていただきました!

では本題です。


UITableViewのSectionHeaderとSectionFooterをdequeuで使いまわしできるようにする

多分難しいことを考えなければ以下のUITableViewDelegateを使って表示していると思います。

僕もそうでした。


ViewController.swift

class ViewController {

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
}
}

extension ViewController: UITableViewDelegate {

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// 適当な高さ
return 80.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return CustomView()
}

}


という感じかと思います。

ただそうすると以下の問題があります。


  • 他のイベント時にSection Header, Section Footerにアクセスすることができません。

  • なんか毎回生成処理するのめんどくさい


ちなみにですが...

UITableViewには以下のメソッドがあります。


  • func headerView(forSection section: Int) -> UITableViewHeaderFooterView?

  • func footerView(forSection section: Int) -> UITableViewHeaderFooterView?

というメソッドがありますが、上記の作り方だとアクセスしてもnilが返ってくるだけです。

このメソッドからアクセスできるようにしたいと思います。


UITableViewHeaderFooterView


最初はクラスで

UITableViewHeaderFooterViewを継承したクラスを作成してregister処理をします。

以下のようなクラスを作成したとします。


CustomTableViewHeaderFooterView.swift

class CustomTableViewHeaderFooterView: UITableViewHeaderFooterView {

// 適当にレイアウト処理を施しているであろうLabel
private let label: UILabel

func setText(_ text: String?) {
self.label.text = text
}

}


これを大好きregister処理をします。

class ViewController {

@IBOutlet weak var tableView: UITableView!

// identifier
private let headerfooterViewIdentifier = "CustomTableViewHeaderFooterView"

override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self

self.tableView.register(CustomTableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: headerfooterViewIdentifier)
}

}

で使うときは

extension ViewController: UITableViewDelegate {

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// 適当な高さ
return 80.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerfooterViewIdentifier)
if let v = view as? CustomTableViewHeaderFooterView {
v.setText("header!!!")
}
return view
}

}

となります。


それではNibファイルを使って

やってみます。

以下のようなCustomTableViewHeaderFooterView.xibを作成してください。

スクリーンショット 2016-11-28 0.25.22.png

接続していきます。

スクリーンショット 2016-11-28 0.30.50.png

これを使用していきます。

class ViewController {

@IBOutlet weak var tableView: UITableView!

// identifier
private let nibName = "CustomTableViewHeaderFooterView"

override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self

let nib = UINib(nibName: nibName, bundle: nil)
self.tableView.register(nib, forHeaderFooterViewReuseIdentifier: nibName)
}

}

で使うときは

extension ViewController: UITableViewDelegate {

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// 適当な高さ
return 80.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: nibName)
if let v = view as? CustomTableViewHeaderFooterView {
v.setText("header!!!")
}
return view
}

}

となります。

ちなみに他のイベントなどでsectionの色を変えたいなどの場合は

// 取得したいseciton

let section = 0
let view = self.tableView.headerView(forSection: section)
view.backgroundColor = UIColor.blue

というように扱うことができます。


終わりに

僕はこれでUITableViewのスクロールに合わせてSectionに下線を表示する、しないを実装しました。


参考