Core Data の iCloud 対応
設定関連
プロジェクト作成時に設定する場合
- Storage: SwiftData
- Host in CloudKit : On
あとから iCloud 対応にする場合
- Signing and Capability
- iCloud 追加
- CloudKit にチェック
- Container 追加してチェック。例:
com.sugoideveloper.SugoiApp
- アプリと同じ識別子が推奨されるようだが、同じでなくても動作はする
- Background Modes 追加
- Background fetch?
- iCloud 追加
各ファイルでの実装
@main - XxxApp
- iCloud でない版と一緒
テンプレ
swift
import SwiftUI
import SwiftData
@main
struct SugoiApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
Book.self, // ← ★ ここを自前のモデルに置き換える、追加する
])
let modelConfiguration = ModelConfiguration(
schema: schema,
isStoredInMemoryOnly: false
)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
識別子を明示的に指定する場合
entitlements の iCloud Container Identifier に設定されていれば問題なさそうであるが、
明示必要なケースもあるそうなので、いったんメモ
swift
let modelConfiguration = ModelConfiguration(
schema: schema,
cloudKitDatabase: .private("iCloud.com.example.SugoiApp")
)
モデル
- どこでも良いが、自分ルールとして PersistentModel フォルダに置くことにした
注意点
iCloud なし版の SwiftData と比べての制約
- iCloud 対応時は unique 制約付与が不可
- プロパティはすべて optional ( = String? 等 ) であること
- プロパティは定義時かコンストラクタで初期値がセットしてあること
そうでないと同期されないし、アプリ実行時のログによく見ると、その旨の警告が出る
テンプレ
swift
import SwiftUI
import SwiftData
@Model
class Book: Identifiable {
var id: UUID = UUID()
var name : String? = ""
var order : Int? = 0
init(
name : String
) {
self.name = name
}
}
ContentView
テンプレ
例は NavigationSplitView を使うとして..
swift
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationSplitView {
BookListView()
} content: {
Text("Directory")
} detail: {
Text("Contents")
}
}
}
一覧の取得
swift
import SwiftUI
import SwiftData
struct BookListView: View {
@Environment(\.modelContext) private var modelContext
@Query private var books: [Book]
@State var selection: Book? = nil
var body: some View {
List(books, id: \.self, selection: $selection) { book in
HStack {
Image(systemName: "square.fill")
//.foregroundStyle(Color(cgColor: calendar.cgColor))
Text(book.name ?? "-")
}
}
}
}