【Swift UIKit】UITableViewの使い方!リストビューの実装方法

【Swift UIKit】UITableViewの使い方!リストビューの実装方法

この記事からわかること

  • SwiftUIKitリスト実装する方法
  • UITableViewを使った方法
  • UITableViewCellクラスとdelegatedataSource意味
  • セクションごとに分割する方法
  • UITableViewDelegate/UITableViewDataSourceプロトコル使い方

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

UITableViewクラスとは?

UIKitフレームワークを使用している場合に以下のようなリスト形式のビューを構築できるのがUITableViewクラスです。複数のデータを見やすく管理するのに適しており、データ数が多くなっても画面からはみ出る分は自動でスクロールビューにしてくれるのでデータ数を意識する必要はありません。

Swift(UIKit)のMVCアーキテクチャーとは?役割と構造まとめ

Swift UIではList構造体を使用することで表示できますが使用方法は異なります。

UITableViewを使用する上でポイント

UITableViewを使用するにあたってポイントとなるのは以下の3つです。

UITableViewCell

@MainActor  class UITableViewCell : UIView

UIKitのリスト表示を行うUITableViewでは1行1行のことを「セル」と呼びUITableViewCellクラスとして管理されます。

delegate

delegateは処理を委任するための仕組みで、UITableViewではセルの個数やセクション数などをデリゲートメソッドとして定義します。

おすすめ記事:【Swift】delegate(デリゲート)とは?使い方とメリット

dataSource

dataSourceは実際にリスト表示するためのデータ元を指します。

リストビューの実装方法

ここからは実際にリストビューを実装していきたいと思います。そのためにはInterface Builderからの操作とコードを記述する必要があります。新規のSwiftプロジェクトを立ち上げた状態から始めていきます。

先にざっと流れを確認しておきます。この順番でなくても動作はしますので自分の中で実装までの流れを決めておくと良いかも知れません。

実装の流れ

  1. Main.storyboardにTable Viewを追加
  2. delegateとdatasourceを紐付け
  3. 表示させるデータの定義
  4. UITableViewDataSourceとUITableViewDelegateプロトコルに準拠したViewControllerクラスの作成
  5. セルの個数とセルを生成するメソッドの定義

新規のプロジェクトを立ち上げたら「Main.storyboard」を開きます。するとInterface Builderが起動するので、空になっているビューに対して「Table View」を追加して画面いっぱいに広げておきます。

【Swift UIKit】UITableViewの使い方!リストの作成方法

プロジェクト立ち上げ時は最初から既存のsceneと既存のViewControllerクラスが紐づいていますので特に設定は変えずにビューを右クリックします。すると以下のようなポップアップが表示されるのでdelegatedataSourceの横からマウスで「View Controller」までつなぎます。これで既存のViewControllerクラスとTableViewとの紐付けが完了しました。

【Swift UIKit】UITableViewの使い方!リストの作成方法

表示させるデータを定義する

続いて表示させるためのデータを定義します。今回は構造体を定義しその型のデータが複数格納された配列形式のサンプルデータを作成しておきました。


import UIKit
struct UserModels {
    var name:String
    var age:Int
}

#if DEBUG
extension UserModels{
    static var sampleData = [
        UserModels(name: "John", age: 20),
        UserModels(name: "Michael", age: 15),
        UserModels(name: "Stephanie", age: 69),
        UserModels(name: "Lloyd", age: 27),
        UserModels(name: "Theodore", age: 42),
        UserModels(name: "Bagwell", age: 30),
    ]
}
#endif

ViewControllerを調整する

既存のViewControllerクラスにUITableViewDataSourceUITableViewDelegateプロトコルの追加とサンプルデータの読み込みをしておきます。UITableViewDataSourceプロトコルを追加したことでセルの個数を返すメソッド(numberOfRowsInSection)セル自体を返すメソッド(cellForRowAt)を定義する必要があります。


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    let userData = UserModels.sampleData
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    // セルの数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.userData.count;
    }

    // セルの生成
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "myCell")
        cell.textLabel?.text = self.userData[indexPath.row].name
        return cell
    }
}

セルの生成には独自でUITableViewCellクラスを定義すればカスタマイズしやすいセルビューを構築することも可能です。詳細は以下の記事をご覧ください。

おすすめ記事:【Swift UIKit】UITableViewCellでカスタムセルビューの作り方!

これでUIKitでリスト表示ができるようになりました。シミュレーターで確認して見てください。

Swift(UIKit)のMVCアーキテクチャーとは?役割と構造まとめ

UITableViewCellの使い方

UITableViewCellクラスを使用してリストのセル単位のビューを構築します。イニシャライザを使用することでセルのスタイルと識別子を設定しています。

let cell = UITableViewCell(style: .default, reuseIdentifier: "myCell")
cell.textLabel?.text = self.userData[indexPath.row].name

UITableViewDelegateプロトコル

公式リファレンス:UITableViewDelegateプロトコル

UITableViewDelegate選択の管理やセクションのヘッダーとフッターの設定、セルの削除や並べ替えなどのデリゲートメソッドを提供するプロトコルです。

デリゲートメソッド名は基本的にtableViewですが引数に渡す値が異なります。また必ず定義しないといけないメソッドはありません。

メソッド 概要
tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat セルの高さを設定
tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat ヘッダーの高さを設定
tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? ヘッダーのビューを設定
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) セルが選択された時に処理を実行

UITableViewDataSourceプロトコル

公式リファレンス:UITableViewDataSourceプロトコル

UITableViewDataSourceリスト表示させるためのデータとセルを管理するためのデリゲートメソッドを提供するためのプロトコルです。

こちらも同様にデリゲートメソッド名は基本的にtableViewですが引数に渡す値が異なりますセルの数とセル自体を返すメソッドは必ず定義する必要があります。

メソッド 概要
tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int セルの数を設定
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell セル自体を返す
numberOfSections(in tableView: UITableView) -> Int セクションの数を設定

セクションごとに分割する

リスト表示しているデータをセクションごとに分割してタイトル(ヘッダー)をつけることも可能です。

【Swift UIKit】UITableViewの使い方!リストの作成方法

まずは表示させるデータを配列から多次元配列に変更し、表示させるセクションタイトル用のデータを配列で準備しておきます。


struct UserModels {
    var name:String
    var age:Int
}

#if DEBUG
extension UserModels{
    static var sampleData = [
    [
        UserModels(name: "John", age: 20),
        UserModels(name: "Michael", age: 15),
        UserModels(name: "Stephanie", age: 69)
    ],[
        UserModels(name: "Lloyd", age: 27),
        UserModels(name: "Theodore", age: 42),
        UserModels(name: "Bagwell", age: 30)
    ]
    ]
    static var sectionTitle =
    ["School","Work"]
}
#endif

続いてデータの読み込みと生成するセルの修正、セクションの数を返す関数(numberOfSections)セクションタイトルを返す関数(titleForHeaderInSection)を定義します。


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    let userData = UserModels.sampleData
    // 追加
    let sectionTitle = UserModels.sectionTitle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    // セルの数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.userData.count;
    }

    // セルの生成
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "myCell")
        // 修正
        cell.textLabel?.text = self.userData[indexPath.section][indexPath.row].name
        return cell
    }
    
    // セクションの数
    func numberOfSections(in tableView: UITableView) -> Int {
        return sectionTitle.count
    }
    
    // セクションタイトルを返す
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionTitle[section]
    }
}

セルやセクションの一部だけを更新する

セルに何かしらの更新が会った際にテーブル全体をリフレッシュするのではなくセルやセクション単位でリフレッシュさせることで冗長な再描画を防ぐことができます。

更新する際はデータの変更を行った後にbeginUpdatesメソッドを呼び出して更新を開始したことを伝えreloadSections/reloadRowsで更新し、endUpdatesで更新を終了します。

let section = 0
userDataTable.beginUpdates()
userDataTable.reloadSections([section], with: .automatic)
userDataTable.endUpdates()
let indexPath = IndexPath(row: 0, section: 1)
userDataTable.beginUpdates()
userDataTable.reloadRows(at: [indexPath], with: .automatic)
userDataTable.endUpdates()

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index