CoreDataとMagicRecordとSwiftUI

CoreDataとSwiftUIに加えて、MagicRecordを使うサンプルを作ってみました。

つかう要素

以下の要素を合わせて使うプロジェクトを作りました。

  • SwiftUI
  • CoreData
  • MagicRecord

最初の2つは、Web上でもよく見つかるのですが、3つすべてを組み合わせた例があまり見つかりませんでした。

普通に動くのか、問題山積みなのか、よくわからないので、自分で作って確かめてみることに。

プロジェクト作成

普通に、SwiftUIとCoreDataを指定してプロジェクト作成。
MagicRecordは、SwiftPackageには対応していないようなので、CocoaPodsでインストールすることに。

いつも通り、いったんプロジェクトを閉じて、コマンドラインで、”% pod init”した後、作成されたPodfileに以下を追加しました。

MEMO
MagicRecordのWebのInstall方法に書いてあるママです。

作成された.xcworkspaceを開いて、作業を継続します。

CoreDataモデルの作成

簡単なモデルを作りました。

  • Record
    • date:Date
    • volume:Double

例えば、毎日どれくらいの水を摂取しているかを記録するアプリを作るイメージです。

SampleCDDataModel

MagicRecordの準備

アプリ起動時のMagicRecord設定

アプリ終了時のMagicRecord設定

applicationWillTerminateとかじゃなく、Sceneがなくなる時にcleanUpするようにしました。

# ここまでの作業を終えて、コンパイルできることを確認。

いろいろとセットアップできたので、さっそく。

SwiftUIでメインのUI作成

SwiftUIの流儀に沿って、NSManagedObjectContextとNSFetchResultを使用。とりあえず、

  • Record要素をListで表示
  • NavigationViewにいれて、各要素をクリックすると詳細ビューへ
  • 右上に+ボタンがあり、押すと、要素追加
  • 左上に編集ボタンがあり、押すと要素削除ができる

Recordの配列をListに表示するUI

ちなみに、CoreDataの要素に対しての簡単なWrapperを作ってます。

MagicRecordとSwiftUI+CoreDataの整合性

と、ここで実行してみるとエラー発生。

SwiftUIは、SceneDelegateでNSManagedObjectContext(長いので、以降MOCと書きます)を作りますが、MagicRecordとconflictするみたい。当たり前ですね。
MagicRecordを優先して使用するために、SceneDelegateでのmoc作成部分をコメントアウトして、.environmentで渡さないようにします。

再度コンパイルするも、エラー。

@FetchRequestは、使いたいと思って残したのですが、Environmentの中の.managedObjectContextを使用しているようで、設定しないとContextが無いというエラーを起こします。

MagicRecord側が用意してくれるFetchRequestを使おうかとも考えたのですが、せっかくの自動更新機能を使わないのはもったいないので、折衷案としました。
つまり、MagicRecordが作ってくれたMOCを.environmentで渡します。
SceneDelegate側で、MagicRecordが使うContextを.environmentに設定

ContentView側では、@FetchRequestを使用。

追加等行うと問題が発生するかもしれませんが、それはその時に。-> 最後までうまく動作しました。

Record追加

+ボタンを押したら、現在の時間を使って、飲んだ水の量を入力することにしましょう。.sheetを使って、表示させます。
入力画面となるDrinkViewは、こんな感じ

DrinkView

DrinkViewを表示するようにしたContentViewは、こちら

いくつか記録した時ののContentView

MainListView

削除等の追加

左へのスライドや、編集ボタンでの変更も実装してみます。
ContentViewは、こんな感じです。

DeleteWaterRecord

まとめ:SwiftUI/CoreData/MagicRecordをまとめて使う

MagicRecordの良い点は、NSManagedObjectContextを内部で渡してくれていて、都度都度引数として渡す必要がない点だと思うのですが、SwiftUIと組み合わせて使うと、「SwiftUIがNSManagedObjectContextを共有しやすい仕組み(environment)を提供してくれている」、「FetchRequestの更新からViewの更新をしてくれる仕組みがある」という点で、MagicRecordの良い点が減ってしまっている気がします。

そうは言っても、おまじないのようなコードなしにEntityを追加出来たりするのは、良いですよね。

しばらく並行して使ってみます。

SwiftUI本

少しづつ慣れてきてはいますが、やはりViewやLayoutのための適切なmodifierを探すのが大変です。
”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、超便利です。日本語版でないかなぁ・・・

SwiftUIViewsMastery

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です