日付、カテゴリなどに基づいたCore Dataエントリのグループ化（iOS 15, SectionedFetchRequest）

取得したCore Dataのデータは、各項目内のプロパティを使用して分類することができます。
例えば、日別のToDo項目を保存している場合、日別に分類し、リストの異なるセクションに表示することができます。

![date-category.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/cd19e1ab-c166-353f-051c-c2a1237bf20e.jpeg)

あるいは、異なるカテゴリーに基づいて収納する場合にも することもできます。

![stars-category.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/3084bad8-c8f9-af21-c60f-a5e6adaa9de6.jpeg)

## ステップ1．キー識別子として文字列を作成する

まず、各カテゴリーがそれを説明する文字列を持っていることに注目してください。
たとえば、項目を日付（これは Date オブジェクトです）で割ると、それを文字列に変換できます（7月2日のように）。

これは、Core Data オブジェクトに拡張機能を追加することで可能になります。

```swift
extension Item {
    @objc
    var dateText: String {
        guard let date = self.dueDate else {
            return "Unknown"
        }
        return DateFormatter.localizedString(from: date, dateStyle: .short, timeStyle: .none)
    }
}
```

この文字列は、グループ化のためのキー（識別子）としても使われるし、UI表示の目的（テーブルビュー内のセクションタイトル）にも使われる。

## ステップ2. セクション化されたフェッチリクエスト `@SectionedFetchRequest` を作成する

`@FetchRequest` の代わりに、`@SectionedFetchRequest` を使用します。

```swift
@SectionedFetchRequest<String, Item>(
    sectionIdentifier: \.dateText,
    sortDescriptors: [SortDescriptor(\.date, order: .reverse)]
)
private var itemSections: SectionedFetchResults<String, Item>
```

ここでは、各セクションの識別子（キー）は `dateText` の値になります（つまり、2つのCore Dataの項目が同じキー（同じdateTextの値）を持っていれば、一緒にグループ化されることになります）。

また、この識別子を変更することで、異なるグループ分けを行うこともできます。
例えば、カテゴリごとにグループ化することができる。

`sortDescriptors` は、結果配列の並び順を記述します。
ここでは、日付の逆順に基づいてソートしています。

## ステップ3．結果をループで処理する

変数 `itemSections` の値は、グループ (セクション) の配列になります。

まず、すべてのグループに対してループ処理を行います。
`ForEach(itemSections) { itemSection in ... }`
各グループに対して、 `.id` 変数で識別子を読み込んで表示します（この例では、 `dateText` の結果です）。

それから、各グループをループしてアイテムを取得することができます。

たとえば、異なるグループのすべてのエントリを表示するSwiftUIのコードは次のとおりです。

```swift
ForEach(itemSections) { itemSection in
    Section(itemSection.id) {
        ForEach(itemSection) { itemEntry in
            VStack(alignment: .leading) {
                Text(itemEntry.content ?? "")
                    .font(.headline)
                Text(itemEntry.dateText)
            }
        }
    }
}
```

![date-category.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/cd19e1ab-c166-353f-051c-c2a1237bf20e.jpeg)

2つのセクションがあり（日の文字列 `dateText` を基準にグループ化）、セクションのタイトルが識別子となります。

同じロジックをUIKitアプリケーションに適用することができます。

## コード例

テストレコードを追加するボタンがあります。
また、Core Dataのエントリーをカテゴリーや時間に基づいてグループ化する機能があります。

カテゴリに基づくグループ化のためのXcodeプロジェクトのサンプルです

https://github.com/mszpro/GroupedFetchRequest_demo

日付を基準にグループ化するためのXcodeプロジェクトのサンプルです

https://github.com/mszpro/GroupedFetchRequest_byDate_demo

---

# 関連記事 (Core Data)

https://qiita.com/MaShunzhe/items/e7263507e07919a6adab

https://qiita.com/MaShunzhe/items/5cc294324f0ecc54c264

https://qiita.com/MaShunzhe/items/2018455cab0803d78442

https://qiita.com/MaShunzhe/items/f3e1b439bb0233be615a

https://qiita.com/MaShunzhe/items/6d13422aee5dcfaf2cc2


---


:thumbsup: お読みいただきありがとうございました。

[☺️ Twitter @MszPro](https://twitter.com/MszPro)
[🐘 Mastodon @me@mszpro.com](https://sns.mszpro.com/@me)

:sunny: <img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">

---
![writing-quickly_emoji_400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/640938e9-c121-8152-b8c4-8ab63124afcc.png)