SwiftDataでつまずいた話:初心者がデータ保存でハマった5つのポイント

SwiftDataでつまずいた話:初心者がデータ保存でハマった5つのポイント トラブルシューティング

飲酒量管理アプリを作る上でどうしても避けて通れないのが「記録したデータをどう保存するか」という問題です。Swift独学ロードマップの段階では触れていなかった、データ保存の仕組み「SwiftData」に初めて触れてみて、実際につまずいたポイントを記録として残します。

SwiftDataとは何か

SwiftDataは、Appleが提供するデータ永続化(保存)のためのフレームワークです。以前はCore Dataという仕組みが主流でしたが、SwiftDataはSwiftの文法に近い書き方でデータの保存・取得ができるように設計されています。

「記録した飲酒量のデータを、アプリを閉じても消えないように保存したい」という今回の目的にはぴったりの仕組みでした。

1. @Modelマクロの意味がすぐに理解できなかった

SwiftDataでは、保存したいデータの構造を@Modelというマクロをつけたクラスとして定義します。

@Model
class DrinkRecord {
    var date: Date
    var amount: Double
}

最初は「なぜこれだけで保存できる仕組みになるのか」がピンと来ませんでした。@ModelをつけたクラスはSwiftDataによって自動的に保存対象として扱われる、という理解にたどり着くまで、ドキュメントを何度も読み返すことになりました。

2. モデルの定義をあとから変更してクラッシュした

一度アプリを実行してデータを保存したあとに、DrinkRecordにプロパティを1つ追加してみたところ、アプリが起動時にクラッシュするようになりました。

原因は、すでに保存されている過去のデータの形と、新しいモデルの形が一致しなくなったことでした。SwiftDataは自動でスキーマ(データの形)をある程度マイグレーション(移行)してくれますが、変更内容によっては手動での対応が必要になる場合があるようです。

開発中は、モデルの構造を変更したらシミュレータのアプリを一度削除してから再インストールする、という運用でしのいでいます。

3. @Queryでデータが更新されない

保存したデータを画面に一覧表示する際、@Queryというプロパティラッパーを使います。

@Query var records: [DrinkRecord]

これだけで一覧が自動更新される、と聞いていたのですが、思ったタイミングで画面が更新されずに困ったことがありました。原因を調べてみると、@Queryを使う場所がSwiftUIの View 構造体の外(別のクラスなど)になっていて、SwiftUIの更新の仕組みがうまく効いていなかったことが分かりました。

@QueryはView構造体の直下で使う、という基本を守ることで解決しました。

4. 新規追加はできるのに削除でエラーになった

一覧からデータを削除する処理で、最初は次のようなコードでエラーが出ました。

modelContext.delete(record)

modelContext(データの出し入れをする窓口のようなもの)を正しく取得できていなかったことが原因でした。@Environment(\.modelContext)で取得する必要があるのですが、この記述を忘れて自分で新しくModelContextを作ってしまっていたのが原因でした。

エラーメッセージだけを見ても原因が分かりにくく、公式サンプルコードを見比べながら気づいた点です。

5. プレビュー画面でだけ正常にデータが表示されない

Xcodeのプレビュー機能(コードを書きながら画面を確認できる機能)で、SwiftDataのデータがうまく表示されないことがありました。

実機やシミュレータでは問題なく動くのに、プレビューだけデータが空になる現象で、最初は原因が分からず焦りました。調べてみると、プレビュー専用の「メモリ上だけの仮のデータベース」を用意して、そこにサンプルデータを入れておく必要があることが分かりました。

.modelContainer(for: DrinkRecord.self, inMemory: true)

このような設定をプレビュー用に追加することで、開発中も安心してデータの見た目を確認できるようになりました。

まとめ

  • @Modelはデータ構造をSwiftDataの保存対象にするための仕組み
  • モデルの変更は既存データとの整合性に注意(開発中は再インストールでしのぐのも手)
  • @QueryはView構造体の直下で使う
  • データの削除には@Environment(\.modelContext)で取得したmodelContextを使う
  • プレビュー用にはメモリ上だけの仮データベースを用意する

エラーメッセージだけでは原因が分かりにくい場面が多く、公式ドキュメントとサンプルコードを行き来しながら理解を進めることになりました。同じようにSwiftDataでデータ保存を実装しようとしている方の参考になれば幸いです。次は、保存したデータをSwiftUIのList・ForEachで一覧表示する過程でつまずいたポイントをまとめます。


本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。

コメント

タイトルとURLをコピーしました