【SwiftUI】Core Dataの使い方:標準テンプレートを読み解く

(2023/03/25 更新)

SwiftUIでのCore Dataの使い方を、標準テンプレートを読み解きながら解説します。

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】14.2
【Swift】5.7.2
【iOS】16.2
【macOS】Ventura 13.2
スポンサーリンク

標準テンプレートの生成

Xcodeで新規プロジェクトを生成します。
プラットフォームはiOSを選択してください。
UntitledImage
「Use Core Data」にチェックを入れます。
UntitledImage

標準でCore Dataを利用したアプリのテンプレートコードが生成されます。

ファイル拡張子の表示

Xcode13以降、Project navigatorでのファイル拡張子は非表示になっています。
わかりやすいように、メニューバーより下記の設定をして、表示させましょう。
Xcode > Settings > General > File Extensions > Show All

UntitledImage
UntitledImage

スポンサーリンク

標準テンプレートを動かす

生成されたテンプレートをシミュレータで実行すると、+ボタンとEditボタンが画面上に表示されます。
「+」ボタンでリストの行追加、Editボタンでリストの編集(削除のみ)が可能になります。

一旦アプリを終了してから再度立ち上げても、リストには前の状況が残っており、永続的なデータ保存が実現が確認できます。

UntitledImage

次章以降で、標準テンプレートの詳細について解説します。

スポンサーリンク

データモデルの定義

Core Dataで扱うデータモデルは、プロジェクト名.xcdatamodeldファイルで定義されています。
下図の「エンティティ名」がDBのテーブル名、「属性情報」がテーブルのカラム情報に相当します。
標準テンプレートでは、属性項目timestampを1つだけ持つ、 Itemテーブルが定義されています。

UntitledImage

このデータモデル定義に従って、Itemクラスが生成されます。
Itemクラスはテーブルの1レコードを格納するクラスで、エンティティの基本クラスである被管理オブジェクト(NSManagedObject)を継承しています。

デフォルトの設定では、ItemクラスのソースコードはXcode上見えません。

スポンサーリンク

リストの表示処理

データベースからデータを取得して、リストに表示する処理は、ContentViewの前半に記述されています。
わかりやすいようにコメントを追加しました。

被管理オブジェクトコンテキスト(ManagedObjectContext)の取得

被管理オブジェクトコンテキスト(ManagedObjectContext)はデータの生成、保存、取得といったデータベース操作に必要な操作を行う為のオブジェクトです。
このオブジェクトを使ってデータベースアクセスする全ての操作を行います。
ManagedObjectContextはアプリ起動時に生成され、環境変数managedObjectContextに登録されています。

データベースよりデータを取得(Fetch処理)

プロパティラッパーの@FetchRequestを使ってデータベースを検索し、対象データ群をitemsプロパティに格納しています。
引数(sortDescriptors)で検索結果のソート条件(Itemテーブルのtimestamp属性が昇順)を指定、
引数(animation)で取得した検索結果の変更時に使用されるアニメーションタイプを.defaultに指定しています。

取得結果が格納されるitemsは被管理オブジェクト(ManagedObject)のコレクションであるFetchedResults型です。
ManagedObjectはテーブルの1レコードに該当するエンティティを保持するクラスで、ObservableObjectに準拠している為、値の変更がSwiftUIのViewと同期します。

取得したデータをリスト表示

検索結果itemsの各レコードを表示するTextビューへのリンクをListに表示しています。
item.timestampの出力形式を、formatterで指定していますが、これはSwiftUIで新たに追加されたLocalizedStringKey型で使えるようになった記述方法です。
なお、出力形式を示すitemFormatterは同じファイル内で次のように定義されています。

List表示処理の最後にある.onDelete()はForEachのModifierです。
コレクション(配列)から要素を削除する操作が行われた際に呼び出す処理(deleteItems)を指定しています。

ナビゲーションバーの設定

ナビゲーションバーの左端にEditボタン、その横に「+」ボタンを設置しています。
「+」ボタンが押された場合は、次章の項目追加処理(addItem関数)が呼ばれます。

最後のTextビューはiOSでは表示されませんが、NavigationViewをNavigationStackに変更するとフッターに表示されます。

UntitledImage

項目追加処理

addItem()ファンクションで「+」ボタンを押された時に呼ばれる項目追加処理を行っています。

新規レコードの作成

ItemクラスのインスタンスであるnewItemを生成し、属性timestampに現在時刻(Date())を設定しています。
Itemクラスのイニシャライザには、引数としてデータベースを操作するManagedObjectContextを渡す必要があります。

データベースの保存

ManagedObjectContextのsave()メソッドで、データベースを保存(コミット)します。
このメソッドはエラーを返す可能性がある為、tryを使ったエラーキャッチが必要です。

アニメーションの指定

新規レコード追加表示時にアニメーションを適用しています。
@FetchRequestで取得したデータ群に対して、既にデフォルトのアニメーションタイプが指定されているので、この記述は蛇足のように思います。

スポンサーリンク

項目削除処理

行の削除が要求された場合は、deleteItems()ファンクションが呼ばれます。

レコードの削除

記述が複雑で、ぱっと見わかりずいらいですが、同様の処理は次のように書き直せます。

offsetsには削除対象の要素番号のコレクションが渡ってきますので、各要素番号に対応したエンティティをループで回して削除します。
削除には対象のエンティティを引数に、ManagedObjectContextのdelete()メソッドを呼び出します。

項目追加処理と同様に、データベースを保存(コミット)が必要です。

スポンサーリンク

アプリ起動時の処理

新規プロジェクト作成時に生成される「プロジェクト名App.swift」ファイル内に、アプリ起動時の処理が記述されています。

永続コンテナのコントローラー生成

Core Dataに必要なオブジェクトの作成と管理を行う永続コンテナ(PersistentContainer)のコントローラーを生成します。
コントローラーの詳細については後述します。

ManagedObjectContextを環境変数に追加

データベース操作に使うManagedObjectContextを環境変数managedObjectContextに設定し、アプリケーションの各Viewで使用可能にします。

スポンサーリンク

永続コンテナコントローラー(PersistenceController)

Core Dataに必要なオブジェクトの作成と管理を行う永続コンテナ(PersistentContainer)のコントローラーで、新規プロジェクト作成時にUse Core Dataチェックを入れると生成されるPersistent.swiftファイルに定義されています。

インスタンスの取得方法には次の2通りあります。

PersistenceController.shared
通常版の永続コンテナコントローラーを返します。

PersistenceController.preview
preview用の永続コンテナコントローラーを返します。
通常版との違いは次の2点です。

  • preview用に初期データが設定される
  • DBが実ファイルでなくメモリ上に構築される(コミットしても永続化されない)
スポンサーリンク

プレビュー(preview)処理

ContentViewを表示するには、環境変数managedObjectContextが設定されている必要がある為、.environmentモディファイアを使って設定しています。
このとき使用しているPersistenceController.previewではプレビュー用のDB初期値が設定されます。

DB初期値は、Persistent.swiftの次の箇所で設定されていますので、ここを書き換えるとプレビュー時の初期値を変更可能です。

スポンサーリンク

合わせて読みたい記事

【SwiftUI】Core Dataの使い方:エンティエィ(Entity)を定義する
(2021/04/26 更新) Xcodeでエンティティを定義する方法を解説します。
【SwiftUI】Core Dataの使い方:準備編
SwiftUIでCore Dataを扱うための前提知識と、新規プロジェクトの作成方法について解説します。
【SwiftUI】Core Dataの使い方:基本編
SwiftUIでCore Dataの基本的な使い方を簡単なTodoリストアプリを例に解説します。
【SwiftUI】Core Dataの使い方:検索編(1/3)
データベースを検索して、オブジェクトとして取得するfetch処理について解説します。 を先に見ておくことをおすすめします。
【SwiftUI】Core Dataの使い方:検索編(2/3)
検索条件を動的に変更する方法を解説します。 の続編です。
【SwiftUI】Core Dataの使い方:検索編(3/3)
前の2つの記事 では、SwiftUIの特徴であるデータバインディングの仕組みを使い、検索結果とViewを紐付ける方法を紹介しました。これにより、検索結果に応じてViewが自動で再描画されます。 しかし、検索結果を別の処理のインプットに使う場...
【SwiftUI】Core Dataの使い方:リレーションシップ編
リレーションシップを使ってエンティティ同士をリンクする方法を解説します。