在 SwiftUI 中,@FetchRequest
是一個非常方便的屬性包裝器(Property Wrapper),用來與 Core Data 整合,並在視圖中自動獲取和顯示資料。這篇教學文將會帶你一步步了解如何使用 @FetchRequest
來從 Core Data 中獲取資料並顯示在 SwiftUI 的畫面上。
首先,我們假設你已經在專案中啟用了 Core Data。如果還沒有,可以在新建專案時勾選 "Use Core Data" 來自動配置。
Core Data 的主要組件包括 NSManagedObjectModel
、NSPersistentStoreCoordinator
、NSManagedObjectContext
等。這些組件在應用程式啟動時會初始化,通常由 AppDelegate 或 SceneDelegate 管理。現代的 SwiftUI 專案可以使用 PersistenceController
來封裝 Core Data 的堆疊:
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "ModelName") // 替換為你的 Core Data 模型名稱
if inMemory {
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores { (description, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
}
var viewContext: NSManagedObjectContext {
return container.viewContext
}
}
接著,定義你的 Core Data Entity。假設我們有一個名為 Task
的 Entity,它有一個 title
(String)屬性和一個 isCompleted
(Boolean)屬性。
import CoreData
@objc(Task)
public class Task: NSManagedObject {
@NSManaged public var title: String?
@NSManaged public var isCompleted: Bool
}
在 SwiftUI 中,可以使用 @FetchRequest
來獲取 Task
資料並在視圖中顯示。下面是一個簡單的例子,將所有的 Task
資料顯示在 List
中:
import SwiftUI
struct TaskListView: View {
// 使用 @FetchRequest 來自動從 Core Data 中獲取 Task 資料
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Task.title, ascending: true)]
) var tasks: FetchedResults<Task>
var body: some View {
NavigationView {
List {
ForEach(tasks) { task in
HStack {
Text(task.title ?? "Untitled")
Spacer()
if task.isCompleted {
Image(systemName: "checkmark.circle")
.foregroundColor(.green)
}
}
}
}
.navigationTitle("Tasks")
}
}
}
在這段程式碼中:
@FetchRequest
用於自動從 Core Data 中取得 Task
實體的資料。entity: Task.entity()
指定了要獲取的實體是 Task
。sortDescriptors
是一個排序描述符,用來定義資料的排序方式。在這裡,我們根據 title
屬性來排序。tasks
是一個 FetchedResults<Task>
,它像是陣列一樣,可以在 SwiftUI 視圖中直接使用。除了顯示資料,你也可以在 SwiftUI 中使用 Core Data 的上下文來增加或刪除資料。以下是如何在 TaskListView
中增加一個任務:
struct TaskListView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Task.title, ascending: true)]
) var tasks: FetchedResults<Task>
var body: some View {
NavigationView {
List {
ForEach(tasks) { task in
HStack {
Text(task.title ?? "Untitled")
Spacer()
if task.isCompleted {
Image(systemName: "checkmark.circle")
.foregroundColor(.green)
}
}
}
.onDelete(perform: deleteTasks) // 刪除功能
}
.navigationTitle("Tasks")
.navigationBarItems(trailing: Button(action: addTask) {
Label("Add Task", systemImage: "plus")
})
}
}
private func addTask() {
withAnimation {
let newTask = Task(context: viewContext)
newTask.title = "New Task"
newTask.isCompleted = false
saveContext()
}
}
private func deleteTasks(offsets: IndexSet) {
withAnimation {
offsets.map { tasks[$0] }.forEach(viewContext.delete)
saveContext()
}
}
private func saveContext() {
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
在這段程式碼中:
@Environment(\.managedObjectContext)
來取得當前的 Core Data 上下文。addTask()
方法會在 viewContext
中新增一個 Task
實體並保存。deleteTasks()
方法使用 onDelete
修飾符來刪除選定的任務。以上的教學介紹了如何使用 @FetchRequest
來從 Core Data 中取得資料,並顯示在 SwiftUI 視圖中。這是 SwiftUI 與 Core Data 整合的強大功能之一,使得資料管理變得非常簡單且直觀。
這份教學也涵蓋了如何在 SwiftUI 中增加和刪除 Core Data 資料的基本操作。