【WWDC23】SwiftDataを用いたApp作成
SwiftUIとSwiftDataを用いたフラッシュカードアプリの作成
公式のサンプルを参考に記事を記載します。
モデルの定義
モデルクラスをSwiftDataに対応させます。以下のようにCard
クラスを定義し、@Model
マクロを追加します。@Model
マクロを使用することによって、Observable
プロトコルに一致するようになり、ObservableObject
の代わりに使えます。
import SwiftData
@Model
final class Card {
var front: String
var back: String
var creationDate: Date
init(front: String, back: String, creationDate: Date = .now) {
self.front = front
self.back = back
self.creationDate = creationDate
}
}
この@Model
マクロにより、Card
クラスは自動的に永続化が可能になります。
データのバインディング
@Bindable
プロパティラッパーを使用して、データモデルをViewにバインドします。
@Bindable var card: Card
これにより、テキストフィールドなどのUI要素が直接モデルにバインドされ、モデルの変更が自動的にUIに反映されます。
データのクエリ
SwiftDataからデータをクエリして表示するには、@Query
を使用します。
@Query private var cards: [Card]
@Query
はSwiftDataからモデルをクエリし、モデルの変更がViewに反映されるようにします。
モデルコンテナの設定
モデルコンテナの設定方法に関してです。
WindowGroup
でモデルコンテナを設定することによって、WindowGroup全体でモデルを使用できます。
Window
ごとに複数のモデルコンテナを設定できます。
下位の階層内において、別でモデルコンテナを設定できます。
WindowGroup
シーンのモデルコンテナを設定します。これにより、ViewがSwiftDataにアクセスできます。
WindowGroup {
ContentView()
}
.modelContainer(for: Card.self)
Previewの表示
サンプルデータを用意します。
struct SampleDeck {
static var contents: [Card] = [
Card(front: "Open Settings in a single click", back: "SettingsLink"),
Card(front: "Configure the toolbar title display size", back: "toolbarTitleDisplayMode(_:)"),
//省略
]
}
Previewコンテナを作成します。
@MainActor
let previewContainer: ModelContainer = {
do {
// ModelContainerを作成し、データをメモリ内にのみ保存し、永続化ストレージを使用せずに使用する設定を追加
let container = try ModelContainer(
for: Card.self,
configurations: ModelConfiguration(isStoredInMemoryOnly: true)
)
let modelContext = container.mainContext
// モデルコンテキストに既存のデータがない場合、サンプルデータを挿入
if try modelContext.fetch(FetchDescriptor<Card>()).isEmpty {
SampleDeck.contents.forEach { container.mainContext.insert($0) }
}
return container
} catch {
// コンテナの作成に失敗した場合、エラーメッセージを出力しアプリケーションを終了
fatalError("Failed to create container")
}
}()
Preview
にpreviewContainer
を設定する。
#Preview {
ContentView()
.frame(minWidth: 500, minHeight: 500)
.modelContainer(previewContainer)
}
モデルコンテキストへのアクセス
モデルコンテキストにアクセスして新しいデータを保存します。SwiftUIでは、Environment
を使用してモデルコンテキストにアクセスします。
@Environment(\.modelContext) private var modelContext
新しいデータを作成し、モデルコンテキストに挿入します。
let newCard = Card(front: "Sample Front", back: "Sample Back")
modelContext.insert(object: newCard)
ドキュメントベースのアプリケーション設定
ドキュメントベースのアプリケーションを設定します。これにより、ドキュメントデータを作成、保存、共有が可能となります。まず、info.plistでドキュメントデータのタイトル・拡張子・identifier(コード内と同一)・ConformsToを設定します。
info.plistで設定したデータ・ファイル形式を使用するために宣言します。
import UniformTypeIdentifiers
extension UTType {
static var flashCards = UTType(exportedAs: "com.example.flashCards")
}
DocumentGroup
にcontentType
を指定して完了です。
@main
struct SwiftDataFlashCardSample: App {
var body: some Scene {
#if os(iOS) || os(macOS)
DocumentGroup(editing: Card.self, contentType: .flashCards) {
ContentView()
}
#else
WindowGroup {
ContentView()
.modelContainer(for: Card.self)
}
#endif
}
}
上記の設定・実装を行うことにより、オリジナルのドキュメントデータを作成し、管理することが可能です。
最後に
間違い・気になる部分がありましたら、コメントいただけると大変うれしいです。
良かったと思ったら記事へのいいね、Xのフォローをよろしくお願いいたします。
個人でアプリを作成しています。良かったら覗いてみてください。
参考資料
Discussion