Help us understand the problem. What is going on with this article?


More than 1 year has passed since last update.


  • tableViewを使う場合, datasourceとdelegateを使って、セルの設定やテーブルのデータを設定します.
  • その結果, 以下のような感じになりがち
import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {

        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

    override func 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.swiftTableViewDataSourceDelegateController.swiftの2つに分けました.
  • TableViewDataSourceDelegateController.swiftにdelegateとdatasourceを書いています.

  • tableviewはxibファイルで作成し, UIViewにサブビューとして追加しています.

  • tableviewcellもxibで作成しています.

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() {

        tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "tableViewCell")

        tableView.delegate = tableViewDataSourceDelegate
        tableView.dataSource = tableViewDataSourceDelegate


import UIKit

typealias UITableViewDD = UITableViewDelegate & UITableViewDataSource

class TableViewDataSourceDelegateController: UITableView, UITableViewDD {

    var tableData: [[String]] = [
        ["a", "b", "c"],
        ["d", "e"],
        ["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を別ファイルにする場合のコツ

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away