はじめに
- tableViewを使う場合, datasourceとdelegateを使って、セルの設定やテーブルのデータを設定します.
- その結果, 以下のような感じになりがち
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = String(indexPath.row)
return cell
}
}
- 最低限のデリゲートのみしか書いてませんが、どんどん増やしていくと見づらいコードになりがちです。
- そこで、これらのdelegateとdatasourceをViewControllerから分離しましょう!がこの記事でお伝えすることです.
実装
-
TableViewController.swift
とTableViewDataSourceDelegateController.swift
の2つに分けました. -
TableViewDataSourceDelegateController.swift
にdelegateとdatasourceを書いています. -
tableviewはxibファイルで作成し, UIViewにサブビューとして追加しています.
-
tableviewcellもxibで作成しています.
TableViewController.swift
import UIKit
class TableViewController: UIViewController {
let tableView = UINib(nibName: "TableView", bundle: nil).instantiate(withOwner: self, options: nil).first as! UITableView
var tableViewDataSourceDelegate: TableViewDataSourceDelegateController = TableViewDataSourceDelegateController()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "tableViewCell")
tableView.delegate = tableViewDataSourceDelegate
tableView.dataSource = tableViewDataSourceDelegate
self.view.addSubview(tableView)
}
}
TableViewDataSourceDelegateController.swift
import UIKit
typealias UITableViewDD = UITableViewDelegate & UITableViewDataSource
class TableViewDataSourceDelegateController: UITableView, UITableViewDD {
var tableData: [[String]] = [
["a", "b", "c"],
["d", "e"],
["f"],
["g", "h", "i", "j", "k"],
]
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return nil
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 20
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return nil
}
func numberOfSections(in tableView: UITableView) -> Int { // sectionの数を決める
return tableData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
cell.textLabel?.text = tableData[indexPath.section][indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt: \(indexPath)")
// タップ後すぐ非選択状態にするには下記メソッドを呼び出します.
tableView.deselectRow(at: indexPath, animated: true)
}
}
最後に
- インターンで学んだことを思い出しながら書いています.
- ViewControllerの肥大化を抑えられるのはありがたいです.
- 記事作成にあたって, 作成したプロジェクトをGitHubにおいてあります.
GitHubレポジトリ
参考
tableView delegate/dataSourceを別ファイルにする場合のコツ
swiftでDelegate/DataSourceを分離したいときに気をつけること