自作クラスの配列を特定の要素でグループ化してTableViewに表示する

#筆者環境

|MacOS|Xcode|Swift|iOS|
|:--:|:--:|:--:|:--:|
|Catalina(10.15.7)|12.4|5.3.2|14.4|

#表示に使うデータを用意

`SampleData`という`groupID`と表示用の`title`を持っただけの簡易的なクラスを作成する。

```swift:SampleData.swift
import Foundation

class SampleData {
    
    let groupID: Int
    let title: String
    
    init(groupID: Int, title: String) {
        self.groupID = groupID
        self.title = title
    }
    
}
```

#表示に使うテーブルを用意
1. `TableView`を配置していい感じにレイアウトの制約をつける
2. `TableView`上に`PrototypeCell`を配置してインスペクタで`Identifier`を設定する(今回は`cell`にした)
3. `TableView`をソースコードと関連づけする
![スクリーンショット 2021-03-17 22.41.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1216004/cfe6dce7-7f26-62d4-a9a3-73d284d76c96.png)


#実装

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    //データを表示するのに使うテーブル
    @IBOutlet weak var tableView: UITableView!
    //表示するデータの元となる配列を用意
    let dataArray: [SampleData] = [SampleData(groupID: 5, title: "aaa"),
                                   SampleData(groupID: 5, title: "bbb"),
                                   SampleData(groupID: 1, title: "ccc"),
                                   SampleData(groupID: 5, title: "ddd"),
                                   SampleData(groupID: 4, title: "eee"),
                                   SampleData(groupID: 1, title: "fff"),
                                   SampleData(groupID: 3, title: "ggg"),
                                   SampleData(groupID: 3, title: "hhh"),
                                   SampleData(groupID: 7, title: "iii"),
                                   SampleData(groupID: 3, title: "jjj"),
                                   SampleData(groupID: 4, title: "kkk"),
                                   SampleData(groupID: 1, title: "lll"),
                                   SampleData(groupID: 1, title: "nnn"),
                                   SampleData(groupID: 5, title: "mmm")]
    //グルーピング後のデータは辞書型なのでTableViewのIndexPathで参照できるようにkeyを保持する配列が必要
    var groupingIDs: [Int] = []
    //グルーピング後の辞書型のデータ
    var groupingData: [Int : [SampleData]] = [:]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //データソースの実装先を指定する
        tableView.dataSource = self
        //SampleDataの配列をgroupIDでグルーピングする
        groupingData = Dictionary(grouping: dataArray) { (data) -> Int in
            return data.groupID
        }
        //辞書型のkeysをIntの配列にキャストして保持しておく
        groupingIDs = [Int](groupingData.keys)
        //ソートしておく
        groupingIDs.sort()
    }
    
}

//TableViewのデータソースを実装してあげる
extension ViewController: UITableViewDataSource {
    //表示するセクションの個数を返してあげる
    func numberOfSections(in tableView: UITableView) -> Int {
        //グルーピング後の辞書の個数を返す
        return groupingData.count
    }
    //セクションヘッダーに表示する文字列を返してあげる
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        //適当にgroupIDを表示してみる
        return "グルーピングID: \(groupingIDs[section])"
    }
    //セクションないに表示するセルの個数を返してあげる
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //グルーピング後の辞書の該当するkeyの要素の個数を返してあげる
        return groupingData[groupingIDs[section]]!.count
    }
    //表示するセルを返してあげる
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //ストーリーボードに配置したcellのIdentifierと同じにする
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        //適当にタイトルを表示してみる
        cell.textLabel?.text = groupingData[groupingIDs[indexPath.section]]![indexPath.row].title
        return cell
    }
    
}

```

#ビルド結果
![スクリーンショット 2021-03-17 23.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1216004/5dfc0eaa-32b0-bba7-2dc1-cb152d39586e.png)

#参考
[【Swift4】メソッド一発で配列をグルーピング](https://qiita.com/k_or_kt/items/a8132cb783affa70f6be)

#最後に
今回作ったプロジェクトをGitHubに載せておきました。動きだけ見たい場合は[こちら](https://github.com/Wingit124/GroupingSample)から
もっといい方法がありましたらコメントにて教えていただけますと喜びます。