2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Swift] UITableViewの備忘録

Last updated at Posted at 2020-10-24

今回の題

todoリストを作る過程でTableViewを使ったので覚えている内にどこかに書き残しておこうという魂胆で書いてます。
特に物珍しいことはしていません。

シングルビューアプリ上のtableViewでセルの

  • 表示
  • 並び替え
  • 削除

を行うくらいの内容です。

諸々のバージョン

  • Swift version 5.3
  • Xcode Version 11.1

メインストーリーボード

以下の状態を作ります。

スクリーンショット 2020-10-24 18.07.52.png

流れは、

  1. デフォルトのViewControllerにNavigationControllerを追加
  2. ViewController上にtableViewを配置
  3. 2のtableView上にtableViewCellを配置
  4. tableViewCellのidentifierをcellに設定

です。

続いて、tableViewのdelegateとdataSourceもメインストーリーボードで設定しておきます。

スクリーンショット 2020-10-24 18.33.36.png

これをしておけば、viewControllerで

tableView.delegate = self
tableView.datasource = self

とか書かずに済みます。
ただ、ここら辺の書き方は現場に合わせるのが一番かと思いますが、どちらが主流なんでしょうね🤔
Swift歴独学数週間の私にはわかりませんが、もしご存知の方がいらっしゃいましたらお教えいただけますと幸いです。

TableViewに配列を表示する

スクリーンショット 2020-10-24 19.53.49.png

viewController

以下のように、tableViewをOutlet接続し、配列を定義します。

ViewController.swift
class ViewController: UIViewController {
    
    // 以下2行を追記
    private var todos = ["卵を買う", "牛乳を買う", "スポンジを買う", "イチゴを買う"]
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

続いて、セルの数セルに表示する内容を定義します。
これらはviewControllerクラス内に定義してもいいのですが、今回はviewControllerを汚さず、かつ可読性を高めるためにextensionを使ってプロトコルごとに定義していきます。

表示するには、UITableViewDataSourceプロトコルの必須メソッドを2つ使います。
以下をviewControllerクラスの下に書きます。

ViewController.swift
extension ViewController: UITableViewDataSource {

    // セルの数を定義。 ここでは配列の数のセルを指定。
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return todos.count
    }
    
    // セルの各行の内容を定義
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel!.text = todos[indexPath.row]
        return cell
    }
}

表示はこれで完成です。

TableViewを操作する

TableViewを操作する際には、主に下の画像にあるメソッドとプロパティを用いて編集モードに切り替えて行います。
スクリーンショット 2020-10-24 20.17.59.png
なのでまず以下でその流れ。

編集モードに切り替える

その1 ボタンを配置

こんな感じになります。
スクリーンショット 2020-10-24 20.31.41.png
まず、navigationBarに編集モードに切り替えるためのボタンを配置します。
ボタンは自前で用意するのではなく、最初に挙げた画像にあるeditButtonItemを使います。
ViewControllerクラスのviewDidLoad()メソッドを以下のように編集します。

ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        // 追記 navigationBarの右側に編集モードに切り替えるためのボタンを配置
        navigationItem.rightBarButtonItem = editButtonItem
    }

その2 メソッドを定義

ViewControllerクラスに以下のメソッドを定義します。
このメソッドはその1のボタンが押されると呼ばれるメソッドで、編集モードに移行する内容になっています。
メソッド内の2行目、isEditingはtrueであれで編集を許可、falseであれば不許可とするプロパティです。

ViewController.swift
    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        tableView.isEditing = editing
    }

これでボタンを押すと以下のように編集モードに切り替えられるようになりました。
スクリーンショット 2020-10-24 21.53.02.png

セルを並び替える

ezgif.com-gif-maker.gif
UITableViewDelegateプロトコルのメソッドをextensionを定義して書き出します。
セルを並び替える為に定義するメソッドは以下の二つ。

ViewController.swift
extension ViewController: UITableViewDelegate {

    // セルの移動を許可する
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    // セル移動時の処理。 セルの移動前の位置と移動後の位置を入れ替える処理を行う。
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let sourceCellItem = todos[sourceIndexPath.row]
        guard let indexPath = todos.firstIndex(of: sourceCellItem) else { return }
        todos.remove(at: indexPath)
        todos.insert(sourceCellItem, at: destinationIndexPath.row)
    }
}

各メソッドの説明はコメントの通りです。

セルを削除する

ezgif.com-gif-maker (1).gif

先ほどのextensionに追記。
追記定義するメソッドは以下の一つだけ。

ViewController.swift
extension ViewController: UITableViewDelegate {
    // 削除を行うメソッド
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        // 配列から削除
        todos.remove(at: indexPath.row)
        // セルから削除
        tableView.deleteRows(at: [indexPath as IndexPath], with: UITableView.RowAnimation.automatic)
    }
}

ただこれだと編集モード時以外でも、セルを横にスワイプすると削除できてしまいます。
そうしたくない時は以下のメソッドを追記します。

ViewController.swift
    // 編集モード中だけ削除を可能に
    func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        if tableView.isEditing {
            return .delete
        }
        return .none
    }

メモ書き

セルの複数選択を有効にする

今回は使いませんでしたが、調べたのでメモしておきます。
ViewControllerのviewDidLoad()に以下を追記します。

ViewController.swift
// 複数選択を可能にする
tableView.allowsMultipleSelectionDuringEditing = true

ただこれを書くと、編集モード中にスワイプで削除はできなくなります。

選択したcellのパスは、

tableView.indexPathsForSelectedRows

で取得できます。

以上!!!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?