Share Extensionの実装を通じてアプリ間連携に理解が深まったところで、以前SwiftDataでつまずいた話を書いた経験と比較しながら、より歴史のあるCore Dataによるデータ永続化にも挑戦してみました。
1. SwiftDataと同じ感覚でモデルを定義しようとした
最初、SwiftDataの@Modelマクロと同じような感覚で、Swiftの構造体やクラスに属性を並べるだけでモデルが定義できると思い込んでいました。
class Memo: NSManagedObject {
@NSManaged var title: String
}
コード上でクラスを定義するだけでは動かず、実際には.xcdatamodeldというビジュアルエディタでエンティティと属性を定義し、コード生成またはこのようなクラス定義と対応付ける必要があることが分かりました。SwiftDataに比べて準備するファイルの種類が多く、最初は戸惑いました。
2. コンテキストの違いを理解せずデータが反映されなかった
データを保存する処理を書いたつもりが、画面に反映されないことがありました。
気づいたこと:
viewContext と別スレッド用のコンテキントを混同していた
Core Dataでは操作対象のNSManagedObjectContextが複数存在しうる仕組みになっており、メイン画面用のviewContextとバックグラウンド処理用のコンテキストを混同すると、保存したはずのデータが画面側に反映されないことがあると分かりました。どのコンテキストで操作しているかを意識する必要がありました。
3. 保存処理を呼び忘れてデータが消えていた
オブジェクトを作成して属性を設定した後、アプリを再起動するとデータが消えていることに気づきました。
try context.save()
SwiftDataでは自動的に保存されるタイミングがあるのに対し、Core Dataではコンテキストへの変更を明示的にsave()で確定させないと永続化されない仕組みだと分かりました。この保存処理を呼び忘れていたことが、データが消えていた直接の原因でした。
4. リレーション先のデータも一緒に消えると誤解していた
親エンティティを削除すれば、関連付けられた子エンティティのデータも自動的にきれいに消えるものだと思い込んでいました。
Delete Rule の設定:
Cascade / Nullify / Deny などから選択する必要がある
実際には、モデルエディタでリレーションごとにDelete Rule(削除時の挙動)を明示的に設定する必要があり、デフォルトの設定によっては親を削除しても子が孤立したまま残ってしまうことがあると分かりました。意図に応じてCascade(連鎖削除)などを選択する必要がありました。
まとめ
- Core Dataのモデル定義はSwiftDataと異なり、
.xcdatamodeldでのエンティティ定義が必要 - 複数存在しうる
NSManagedObjectContextを混同すると、保存したデータが画面に反映されないことがある - 変更はコンテキストへの
save()を明示的に呼ばないと永続化されない - リレーション先データの扱いは
Delete Ruleで明示的に設定する必要がある
同じ「データ永続化」という目的でも、SwiftDataとCore Dataでは設計思想がかなり異なると実感した実装でした。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント