SwiftDataを使ってみた
What SwiftData?
SwiftData は宣言的なコードを使用してデータを簡単に永続化します。通常の Swift のコードを使用して、データをクエリし、フィルタリングすることができます。そして、SwiftUI とシームレスに統合するように設計されています。
「と書いてある」
ローカルDBでは、Realm、CoreDataが有名だが、SwiftDataは何が良いのか???
公式によると
Swift でモデルを作成
Modelを使うことで、追加のファイルやツールを管理することなく、通常のSwift型を使ってデータをモデリングできます。SwiftDataは自動的に多くの関係を推測し、制約を記述するために#Uniqueのような明確な宣言を使うことができます。SwiftUI のように、真実のソースはあなたのコードの中にあります。
@Model
class Recipe {
@Attribute(.unique) var name: String
var summary: String?
var ingredients: [Ingredient]
}
自動永続化
SwiftData はモデルを使用してカスタムスキーマを構築し、そのフィールドを基礎となるストレージに効率的にマッピングします。SwiftData によって管理されるオブジェクトは、必要なときにデータベースから取得され、適切なタイミングで自動的に保存されます。ModelContext API を使って完全に制御することもできます。
カスタムデータストア
デフォルトでは、SwiftDataは永続化のためにCore Dataを使用しますが、新しいDataStoreプロトコルを使用して独自の永続化レイヤーを実装することもできます。DataStoreを使用することで、SwiftDataのAPIはSwiftUIとSwiftDataのモデリングコードを変更することなく、JSONファイルからWebサービスとデータベースエンジンまで、多くの種類の永続化で使用することができます。
SwiftUIと統合する
データを取得するためにSwiftUIのビューで@Queryを使用します。SwiftData と SwiftUI は、基礎となるデータが変更されたときに、手動で結果を更新することなく、ビューにライブアップデートを提供するために連携します。
@Query var recipes: [Recipe]
var body: some View {
List(recipes) { recipe in
NavigationLink(recipe.name, destination: RecipeView(recipe))
}
}
Swiftネイティブ述語
コンパイラによってチェックすることができる Swift ネイティブの型を使用してデータをクエリとフィルタリングすることで、開発中に問題を早期に発見することができます。述語は、式が基礎となるストレージエンジンにマッピングできないときに、コンパイル時のエラーを提供します。
let simpleFood = #Predicate<Recipe> { recipe in
recipe.ingredients.count < 3
}
CloudKit同期
データはDocumentGroupを使ってファイルに保存し、iCloud Drive経由で同期することもできますし、CloudKitを使ってデバイス間でデータを同期することもできます。
Core Dataとの互換性
SwiftDataはCore Dataの実績のあるストレージアーキテクチャを使用しているので、同じアプリで同じ基礎となるストレージで両方を使用することができます。準備ができたら、XcodeはあなたのCore DataモデルをSwiftDataで使用するためのクラスに変換することができます。
どうやって使えば良いの詳しくは、書いておりませんね。海外の動画見てチュートリアルをやってみました。
スキーマを作成する
データベースを扱うためのスキーマを作成しましょう。初期化の処理と自動連番のidを生成する処理を記述したら完成です。Realmよりモデルの定義もロジックを書くのも簡単でした。
import Foundation
import SwiftData
// データスキーマを定義
@Model
class DataItem: Identifiable {
var id: String
var name: String
// 初期化する処理を書く
init(name: String) {
// uuidを文字列に初期化
self.id = UUID().uuidString
self.name = name
}
}
アプリケーションのエントリーポイントに、データーを永続化するコンテナを作成する必要があるので、以下のように作成する。
import SwiftUI
import SwiftData
@main
struct SwiftDataTutorialApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
// データを永続化するコンテナを作成
// パラメータとして型を渡す場合は、.selfという名前をつける。
.modelContainer(for: DataItem.self)
}
}
今回は、ハードコーディングしてますが、データを追加・表示・更新・削除する処理を作りました。@Environment
を使って、構造体から、contextを読み込むことで、SwiftDataを操作できるようになります。
import SwiftUI
import SwiftData
struct ContentView: View {
// このコンテキストを通じてすべての追加・更新・削除を実行できる
@Environment(\.modelContext) private var context
// all data fetch
@Query private var items: [DataItem]
var body: some View {
VStack {
Text("add data!")
Button("Add an Item") {
addItem()
}
// show array data
List {
ForEach(items) {item in
HStack {
Text(item.name)
Spacer()
Button {
updateItem(item)
} label: {
Image(systemName: "arrow.triangle.2.circlepath")
}
}
}.onDelete { indexes in
for index in indexes {
deleteItem(items[index])
}
}
}
}
.padding()
}
func addItem() {
// Create the item
let item = DataItem(name: "Test Item")
// Add the item to the data context
context.insert(item)
}
// update
func updateItem(_ item: DataItem) {
// Edit the item data
item.name = "updated Test Item"
// Save the context
try? context.save()
}
// delete
func deleteItem(_ item: DataItem) {
context.delete(item)
}
}
動作はこんな感じですね。
[追加]
[表示]
[更新]
[削除]
まとめ
SwiftDataを使ってみた感想ですが、簡潔なコードでローカルにデータを保存するビジネスロジックを作ることができるので、とても便利なものでした。注意点としては、iOS17からしか使用できないようです。ですので、iOSのバージョンアップ対応が必要です。
Discussion