iOS SwiftData 本地資料庫教學
SwiftData 是 Apple 在 2023 年推出的全新資料庫框架,旨在取代 Core Data。它完全為了 SwiftUI 設計,結合了 Macro 語法,使用起來就像操作一般的 Swift Class 一樣簡單。
定義模型 (@Model)
只需要在 Class 前面加上 @Model,它就變成一個資料庫表格 (Table)。
import SwiftData
@Model
class TodoItem {
// 1. 使用 @Attribute(.unique) 確保標題不重複
@Attribute(.unique) var title: String
var createdAt: Date
var isCompleted: Bool
// 2. 關聯 (Relationship)
// 假設我們有另一個 Category 模型,這裡定義「多對一」關係
var category: Category?
init(title: String, category: Category? = nil) {
self.title = title
self.createdAt = Date()
self.isCompleted = false
self.category = category
}
}
@Model
class Category {
@Attribute(.unique) var name: String
// 定義「一對多」關係,並設定刪除規則 (當分類被刪除時,其下的 Item 也一併刪除)
@Relationship(deleteRule: .cascade, inverse: \TodoItem.category)
var items: [TodoItem] = []
init(name: String) {
self.name = name
}
}
設置容器 (.modelContainer)
在 App 的進入點注入 ModelContainer。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
// 啟用 SwiftData,並註冊所有需要用到的 Model
.modelContainer(for: [TodoItem.self, Category.self])
}
}
Preview 預覽設定
若是為了 Xcode Preview,我們可以建立一個記憶體容器 (In-Memory Container):
@MainActor
let previewContainer: ModelContainer = {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try! ModelContainer(for: TodoItem.self, configurations: config)
// 塞入假資料...
return container
}()
#Preview {
ContentView()
.modelContainer(previewContainer)
}
操作資料 (CRUD)
讀取與過濾 (@Query)
使用 @Query 並搭配 #Predicate macro 來進行高效過濾。
struct ContentView: View {
@Environment(\.modelContext) private var context
// 1. 基本查詢 (依時間排序)
@Query(sort: \TodoItem.createdAt, order: .reverse) private var items: [TodoItem]
// 2. 過濾查詢 (只顯示未完成的項目)
@Query(filter: #Predicate<TodoItem> { !$0.isCompleted }, sort: \.createdAt)
private var activeItems: [TodoItem]
var body: some View {
List {
ForEach(items) { item in
HStack {
Text(item.title)
Spacer()
if item.isCompleted {
Image(systemName: "checkmark")
}
}
// 點擊切換完成狀態 (更新資料)
.onTapGesture {
item.isCompleted.toggle()
// SwiftData 會自動追蹤變更並存檔,無需手動 save()
}
}
.onDelete(perform: deleteItems)
}
}
func deleteItems(at offsets: IndexSet) {
for index in offsets {
let item = items[index]
context.delete(item) // 刪除資料
}
}
}
新增 (Create)
func addItem() {
let newItem = TodoItem(title: "寫程式")
context.insert(newItem) // 插入資料
// 系統會自動存檔,不用手動 save()
}
更新 (Update)
SwiftData 的物件是 Observable 的。只要你在查詢出來的物件上修改屬性,UI 會自動刷新,資料庫也會自動更新。
// 直接修改屬性即可
item.title = "新標題"
item.isCompleted = true
這與 Core Data 有什麼不同?
SwiftData 其實底層仍然是 Core Data,但它隱藏了所有複雜的設定(如 .xcdatamodeld 檔案、NSManaedObjectContext 的手動儲存等)。
| 特性 | SwiftData | Core Data |
|---|---|---|
| 定義模型 | 純 Swift Code (@Model) | 圖形介面 (.xcdatamodeld) |
| 資料儲存 | 自動儲存 (Auto-save) | 需要手動 context.save() |
| 查詢語法 | Swift-like (#Predicate) | Objective-C 風格 (NSPredicate) |
| 學習曲線 | 低 | 高 |
對於新的 iOS 17+ 專案,強烈建議直接使用 SwiftData。