[iOS][UITableView] リストを並び替える画面を作成する

本記事ではUITableViewを使ってリストを並び替える画面を作成する実装を紹介します
2021.12.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。モバイル事業部の平屋です。

UITableViewを使ってリストを並び替える画面を作成する実装を試してみましたので紹介します。

サンプルアプリ

本記事では以下のような画面を作成します。

検証環境

  • macOS Big Sur 11.4
  • Xcode Version 13.1

基本機能の実装

// (1)
class ViewController: UITableViewController {
    // (2)
    var values = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

    // ...

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // (3)
        return values.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // (4)
        let value = values[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = value
        return cell
    }

    // ...
}

(1) ViewControllerの追加

本記事のサンプルでは、UITableViewControllerのサブクラスとしてViewControllerを定義しました。

また、Storyboardに関しては以下の変更を行いました。

  • プロジェクト作成時に自動生成されるViewControllerを削除
  • TableViewControllerを追加し、クラスとしてViewControllerを指定
  • Cellの設定を変更
    • StyleをBasicに変更
    • IdentifierにCellを指定

(2) データを保持するプロパティの追加

今回は、[String]型のプロパティを追加し、画面に表示し、このデータの順序を並び替えれるようにします。

(3)(4) データ表示に必要最低限のメソッドの実装

以下の2つのメソッドをオーバーライドし、データを表示できるようにします。

  • func tableView(_:numberOfRowsInSection:)
  • func tableView(_:cellForRowAt:)

動作確認1

この時点でアプリを実行すると以下の内容の画面が表示されます。

並べ替え機能の実装

続いて、並べ替え機能を実装していきます。

class ViewController: UITableViewController {
    // ...

    override func viewDidLoad() {
        super.viewDidLoad()

        // (5)
        isEditing = true
    }

    // ...

    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // (6)
        return true
    }

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        // (7)
        let itemToMove = values.remove(at: sourceIndexPath.row)
        values.insert(itemToMove, at: destinationIndexPath.row)
    }

    override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        // (8)
        return .none
    }

    override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
        // (9)
        return false
    }
}

(5) 編集モードをONにする

UITableViewには「編集モード」があり、このモードにすると、Cellに「並べ替え」や「削除」のアイコンを表示できます。 本記事のサンプルでは、常に並べ替え用のUIを表示したいので、画面生成時にisEditingプロパティをtrueにするようにしました。

(6) 並び替えを許可する

以下のメソッドをオーバーライドし、並び替えを許可します。本記事のサンプルでは、全てのセルを並び替えできるようにしたいので、常にtrueを返すようにしました。

  • func tableView(_:canMoveRowAt:)

(7) 並び替えをハンドリングする

以下のメソッドをオーバーライドし、並び替えをハンドリングします。

  • func tableView(_:moveRowAt:to:)

ユーザーが並び替えを行うと、UITableViewはUIを更新します。しかし、データ自体の更新はUITableViewを使う側が行う必要があります。2, 3番目の引数が移動元/移動先のIndexPathになっているので、これを使ってデータを更新します。

(8)(9) 削除ボタンを非表示にする

本記事のサンプルでは、削除ボタンが不要なので、以下のメソッドをオーバーライドして削除ボタンを非表示にし、

  • tableView(_:editingStyleForRowAt:)

また、以下のメソッドをオーバーライドしてインデントを削除するようにしました。

  • tableView(_:shouldIndentWhileEditingRowAt:)

動作確認

ここまで実装してアプリを実行すると、以下のように並び替えを実行できます。

参考資料