[SwiftUI] Document App と CoreData の関係

Xcode12 の生成する Document App と CoreData の関係性を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Big Sur 11.1
  • Xcode 12.3
  • iOS 14.2

Xcode 12.3 のウィザードの謎

Xcode でプロジェクトを作成する時に通過する以下のウィンドウ

Choose a template for your new project
Choose a template for your new project
Choose options for your new project
Choose options for your new project

選択するテンプレートやオプションによって、その後に選択することのできるオプションが変わっていきます。

よくできているのですが、一部、予想と違うことになります。

  • Multiplatform - Document App を選択すると、CoreData の選択肢が現れない
  • macOS - Document App を選択すると、
    • Life Cycle に SwiftUI App を選択すると、CoreData が選択できない
    • Life Cycle に AppKit App Delegate を選択すると、CoreData も選択できる
  • iOS - Document App を選択すると、Life Cycle に何を選んでも CoreData は選択できない

言い方を変えると、CoreData を使った Document App のテンプレートを作りたければ、macOS - Document App で AppKit App Delegate を選択しないといけない ということです。

将来的に、Multiplatform - Document App でも CoreData を含めたテンプレートを生成して欲しいと思いますが、それまでは、自分で追加していかないといけないようです。

macOS 向けのテンプレートをチェック

現時点では、Document App で CoreData を選択できるのは、macOS 向けだけなので、以下のケースでどのようなテンプレートが生成されるかをチェックしてみます。

  • アプリ名:DocAppCoreData macOS - Document App - AppKitAppDelegate で CoreData 選択
  • アプリ名:DocAppSwiftUI macOS - Document App - SwiftUI App を選択

ぼんやりしたゴールとしては、後者にどのようなコードを追加していくと SwiftUI の提供する App Lifecycle に沿って、CoreData を使えるようになるのかの見通しをつけたい

コードの差異

生成されるファイルの比較

それぞれ、以下のようなファイルがテンプレートとして生成されます。

生成されたファイル
生成されたファイル

差異の詳細:共通ファイル

どちらにも含まれるファイルは、以下のファイルです

ContentView.swift
中身は別物。DocAppCoreData の方は、Hello World。DocAppSwiftUI の方は、Document を受け取り表示するビュー
Info.plist
Storyboard に関連する設定に差異がありますが、基本同じ
<app>.entitlements
同じ

差異の詳細;DocAppSwiftUI のみにあるファイル

<app>Document.swift
FileDocument 準拠のドキュメントテンプレート
<app>App.swift
DocumentGroup ビューを使って、ファイルダイアログ表示を担当 (Life Cycle で SwiftUI を選択しているため App 準拠)

差異の詳細;DocAppCoreData のみにあるファイル

Document.swift
makeWindowController 等、NSPersistentDocument 準拠の従来の AppKit の作法に沿ったドキュメントテンプレート
AppDelegate.swift
AppDelegate の空テンプレート(Life Cycle で App Kit AppDelegate を選択しているため)
.xcdatamodeld
CoreData のモデルファイル("Choose options for your new project" で CoreData を選択しているため)

差異まとめ

ぱっと見ですが、コードの差異よりも、plist の差異の方が手間がかかりそうです。

テンプレートコード生成後に、Life Cycle の変更(例えば、SwiftUI App Lif Cycle → App Kit AppDelegate)をするのは、大変そうなので、使いたい Life Cycle を優先して選択して、その後対応させる方が、検証がしやすそうです。

Document App で Life cycle SwiftUI に CoreData を追加

DocAppSwiftUI に、CoreData を追加していくととで、Document App で CoreData を使うためには、以下の手順が必要になりそうです。

  • CoreData モデルの追加
  • <app>Document に、NSPersistentContainer を保持
  • Bundle を作って、.sqlite, .sqlite-shm, .sqlite-wal をまとめて扱えるようにした方が使い勝手は良さそう

まとめ:macOS - Document App で SwiftUI LifeCycle で CoreData を使うには

以下のような手順で進めるのが良さそうです。

macOS - Document App で SwiftUI LifeCycle で CoreData を使うには
  • macOS - Document App でプロジェクト作成を開始
  • Life Cycle に SwiftUI を選択
  • CoreData モデルファイルを プロジェクトに追加
  • FileDocument 準拠ファイルに NSPersistentContainer を保持させる
  • (option) Document は Bundle にして、 CoreData ファイルの関連ファイルを隠した方がよさげ

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

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