[Swift3] UITableViewの基本的な使い方とリスト作成サンプル

2016年11月11日(更新: 2017年8月31日)

UITableView とは、次のようなリストを作るためのUIコンポーネントです。

UITableViewで作ったチェックリスト

UITableView は、左右に画像を配置したり、スワイプでメニューを開いたりと様々な機能をつけることができるため汎用性が高く、iOSアプリを構成する数あるUIコンポーネントの中でも、かなり頻繁に使われるUIだと思います。

今回は Swift での UITableView の基本的な作り方と使い方をサンプルコードとともに紹介します。

UITableView を使ったサンプルアプリ

今回はリスト項目(セル)が5つ表示される以下のようなリストを表示するアプリを作ってみます。

UITableViewを使ったリストのサンプル

サンプルコード

Xcodeで新規プロジェクトをテンプレート「Simple View Application」で作ったときにできる ViewController.swift を書き換えていきます。

Xcode の Single View Application のテンプレート

上の画像のリストを作成する全ソースコードは以下の通りです。

サンプルコードの各部の詳しい解説は後ほど行います。

ViewController.swift

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    // ステータスバーの高さ
    let statusBarHeight = UIApplication.shared.statusBarFrame.height
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // UITableView を作成
        let tableView = UITableView()
        
        // サイズと位置調整
        tableView.frame = CGRect(
            x: 0,
            y: statusBarHeight,
            width: self.view.frame.width,
            height: self.view.frame.height - statusBarHeight
        )
                
        // Delegate設定
        tableView.delegate = self
        
        // DataSource設定
        tableView.dataSource = self

        // 画面に UITableView を追加
        self.view.addSubview(tableView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    // MARK: - UITableViewDataSource
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // セルを作る
        
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        cell.accessoryType = .detailButton
        cell.textLabel?.text = "セル\(indexPath.row + 1)"
        cell.detailTextLabel?.text = "\(indexPath.row + 1)番目のセルの説明"
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // セルの数を設定
        return 5
    }
    
    // MARK: - UITableViewDelegate
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // セルがタップされた時の処理
        print("タップされたセルのindex番号: \(indexPath.row)")
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // セルの高さを設定
        return 64
    }
    
    func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        // アクセサリボタン(セルの右にあるボタン)がタップされた時の処理
        print("タップされたアクセサリがあるセルのindex番号: \(indexPath.row)")
    }
}

サンプルコードの解説

ステータスバーの高さを取得

ステータスバー(時刻やバッテリー残量などが書かれているバー)の高さを取得します。

この値は、後ほど UITableView の表示位置を設定するときに使います。

// ステータスバーの高さ
let statusBarHeight = UIApplication.shared.statusBarFrame.height

UITableViewの生成と位置とサイズ調整

他のUIコンポーネントと同様に、クラスからインスタンスを作成して、プロパティ frame に表示位置(左上の座標)と大きさを CGRect を使って設定します。

位置のy座標を 0 にしてしまうと、UITableView にステータスバーが被ってしまいますので、先ほど取得したステータスバーの高さ分だけ UITableView のy座標を下にずらします。

width は画面と同じ幅でいいのですが、高さは画面サイズからステータスバー分の高さを引いています。

これは、開始位置のy座標をステータスバーの高さだけ下にずらしましたので、UITableView の高さを画面の高さと同じにしてしまうと、ずらした分だけ画面外に飛び出た状態になってしまうからです。

以上のことから、位置とサイズを調整するコードは以下のようになります。

        // UITableView を作成
        let tableView = UITableView()
        
        // サイズと位置調整
        tableView.frame = CGRect(
            x: 0,
            y: statusBarHeight,
            width: self.view.frame.width,
            height: self.view.frame.height - statusBarHeight
        )

プロトコル UITableViewDelegate と UITableViewDataSource の設定

UITableView を使う上で最も重要なことは、プロトコル UITableViewDelegateUITableViewDataSource を設定することです。

        // Delegate設定
        tableView.delegate = self
        
        // DataSource設定
        tableView.dataSource = self

UITableViewDelegate は、セルがタップされた時に処理を行うメソッドセルの高さ設定のメソッドなどが実装されており、このプロトコルを UITableView に紐づけることで、これらのメソッドを適切なタイミングで呼び出すようにできます。

同様に UITableViewDataSource は、セルのデータ(セルのタイトルや見栄えなど)やセルの表示数などを設定するためのメソッドを提供します。

クラス ViewController の宣言時に、以下のようにクラスをプロトコルに適合させる記述を忘れないようにしてください。

...
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
...

リストの項目を UITableViewCell で作る

リスト項目(セル)は、クラス UITableViewCell を利用して作ります。

UITableViewCell(style:reuseIdentifier:)

第1引数 style には、セルのタイプを指定します。システムで用意されているセルのタイプには以下のようなものがあります。

UITableViewCellStyle.default

タイトルのみのセルです。

UITableViewCellのスタイル default

UITableViewCellStyle.subtitle

タイトルの下に説明文が表示されるセルです。今回のサンプルではこれを使っています。

UITableViewCellStyle.value1

説明文がタイトルの右側に表示されるセルのスタイルです。

UITableViewCellのスタイル value1

UITableViewCellStyle.value2

タイトルが青文字となり、その右側に説明文が表示されるセルのスタイルです。

UITableViewCellのスタイル value2

これ以外にも自作のスタイルを設定することができます。

第2引数 reuseIdentifier は、セルを再利用する際に必要となるIDを設定しますが、今回は特に意識する必要はありません。

let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")

UITableViewCell の見栄えを設定

表示するボタンやテキストなどの設定です。

プロパティ accessoryType には、セルの右側に表示するボタン(アクセサリボタン)の種類を設定できます。

今回はINFOボタンを表示したいので .detailButton を設定します。

プロパティ textLabel はセルのタイトルラベルを指します。このタイトルラベルのプロパティ text に代入した文字列がセルのタイトルとなります。

同様に、プロパティ detailTextLabel のプロパティ text に説明文を設定します。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // セルを作る
        
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        cell.accessoryType = .detailButton // セル右側のボタンのタイプ
        cell.textLabel?.text = "セル\(indexPath.row + 1)" // タイトル
        cell.detailTextLabel?.text = "\(indexPath.row + 1)番目のセルの説明" // 説明文
        
        return cell
    }

indexPath.row について

UITableView を設定する様々なメソッドは、引数に indexPath というものがあります。

これは、そのメソッドで処理しているセルの情報が入っている変数です。

例えば、セルのインデックス番号(0から始まるセルの順番を表す値)は、indexPath のプロパティ row に格納されています。

したがって (indexPath.row + 1) とすれば、1番上のセルが1番として数えられるので、サンプルのように一つ目のセルを1として数えることができます。

セルの表示数を設定する

UITableViewDataSource にある以下のメソッドの戻り値が UITableView に表示するセルの数を表します。UITableView のサイズがいくらであろうと、これを設定しない限りセルは一つも現れないので注意が必要です。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // セルの数を設定
        return 5
    }

セルがタップされた時の処理を設定

セルがタップされると、以下のメソッドが呼ばれます。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

indexPath.row にはタップされたセルのインデックス番号が入っていますので、この値を使ってどのセルがタップされたかを判別できます。

サンプルでは、ログにタップされたセルのインデックス番号を表示します。

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // セルがタップされた時の処理
        print("タップされたセルのindex番号: \(indexPath.row)")
    }

タップされたセルの番号を表示

セルのアクセサリボタンされた時の処理を設定

先ほど設定した、セルの右側に表示されるボタン(サンプルではINFO)がタップされたときの処理は、以下のメソッドで設定します。

func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath)

サンプルでは、これもタップされたボタンを含んでいるセルのインデックス番号を表示しているだけです。

    func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        // アクセサリボタン(セルの右にあるボタン)がタップされた時の処理
        print("タップされたアクセサリがあるセルのindex番号: \(indexPath.row)")
    }

セルの高さを調整

以下のメソッドの戻り値がセルの高さを決定します。

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

サンプルでは、全てのセルの高さを 64 にしています。

このメソッドも indexPath を受け取ることができるため、セルによって高さを変えることができます。

例えば以下のようにすると、だんだん大きくなるセルが作れます。

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // セルごとに高さを変更
        return 30 * CGFloat(indexPath.row + 1)
    }

UITableViewでセルごとに高さを設定する

以上が UITableView の基本的な使い方です。値を変えたり、他の設定メソッドを使ったりしてどんなカスタマイズができるか色々試してみてください。

記事冒頭のようなチェックリストを作成する方法については以下の記事を御覧ください。

[Swift3] 画像付きUITableViewでチェックリストを作る

[Swift3] UITableViewの基本的な使い方とリスト作成サンプル」への5件のフィードバック

  1. tableViewの数を指定したい場合はどうすればいいですか?
    例えばcellの数を10個だけにしたい場合はどうすればいいですか?

    返信
  2. すいませんよく読んでみたら書いてありました
    大変参考になりました
    それともしよかったらチェッカー付きのtableViewの作り方を教えていただけませんか?
    一番最初のサンプルの朝食後のtabelViewの作り方をぜひ知りたいです

    返信
    1. JoyPlot 投稿作成者

      記事をご覧いただきありがとうございます。

      チェッカー付きの UITableView の作り方ですが、UITableViewCell のプロパティである imageView?.image に UIImage で画像を設定して、タップした時に画像を切り替えています。

      ざっくり書くと以下のような感じです。

          ...
      
          // セルの作成
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                      
              let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
              cell.textLabel?.text = "テキスト"
              
              if チェックされている {
                  cell.imageView?.image = UIImage(named: "checked")
              } else {
                  cell.imageView?.image = UIImage(named: "unchecked")
              }
              
              return cell
          }
      
          // セルがタップされた時の処理
          func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
              
              if let cell = tableView.cellForRow(at: indexPath) {
                      // 画像をチェック状態のものに変更
                      cell.imageView?.image = UIImage(named: "checked")
      
                      // ここでチェック状態が変更されたことのフラグを保存する
              }
          }
          ...
      

      実際にはチェック状態の情報を UserDefaults などに保存する必要があります。

      詳しくは改めて記事にまとめたいと考えておりますので、今しばらくお待ちいただければと思います。

      返信
  3. ピンバック: [Swift3] 画像付きUITableViewでチェックリストを作る | JoyPlotドキュメント

  4. ピンバック: [Swift] UICollectionViewの使い方 サムネイル一覧画面のようにセルを並べる | JoyPlotドキュメント

コメントを残す

メールアドレスが公開されることはありません。