@FetchRequest 是 SwiftUI 提供的一个属性包装器(Property Wrapper),用于在 SwiftUI 视图中自动获取 Core Data 数据。
它会从 NSManagedObjectContext 中提取数据并监听数据变化。
如果数据发生变化,@FetchRequest 会自动更新 SwiftUI 视图。
基本语法
@FetchRequest(
entity: [实体名称].entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \[实体名称]. [实体属性], ascending: true)]
)
var tasks: FetchedResults<[实体名称]>
例如,存在一个 .xcdatamodeld 文件中,有一个名为“Task”的实体,该实体包含name和timestamp两个属性。

@FetchRequest需要修改为:
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)]
)
var tasks: FetchedResults<Task>
代码解析
@FetchRequest(
entity: Task.entity(), // 1. 实体 (Entity)
sortDescriptors: [ // 2. 排序描述符 (Sort Descriptors)
NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)
],
predicate: NSPredicate(format: "name == %@", "John") // 3. 过滤条件 (Predicate) [可选]
)

1、entity
Task.entity() 指定获取的 Core Data 实体。
需要在 .xcdatamodeld 中定义 Task 实体。

2、sortDescriptors
使用 NSSortDescriptor 来对数据进行排序。
keyPath:指定要排序的属性。
ascending:true 表示升序,false 表示降序。
3、predicate(可选)
NSPredicate 用于过滤数据。
格式示例:
NSPredicate(format: "name == %@", "John")
FetchedResults 的作用
@FetchRequest 返回的数据类型是 FetchedResults<Entity>。
FetchedResults 充当一个数组,可以使用 ForEach 遍历并在视图中显示数据。
示例
import SwiftUI
import CoreData
struct TaskListView: View {
// 使用 @FetchRequest 获取 Task 数据
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)]
)
var tasks: FetchedResults<Task>
var body: some View {
List {
ForEach(tasks, id: \.self) { task in
Text("\(task.name ?? "No Name")")
}
}
}
}
tasks 是 FetchedResults<Task> 类型,类似于一个数组,可以在 ForEach 中进行遍历。
每个 task 都是 Task 实体的一个实例,可以访问其属性(如 task.name)。
使用 @FetchRequest 时的注意事项
1、需要 managedObjectContext 注入
@FetchRequest 依赖于 Core Data 的 managedObjectContext。
在 App 主入口需要通过 .environment() 注入 viewContext:
@main
struct MyApp: App {
let container = NSPersistentContainer(name: "YourProjectName")
init() {
container.loadPersistentStores { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
}
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, container.viewContext)
}
}
}
2、监听数据变化
@FetchRequest 会自动监听 Core Data 数据的变化,当数据更新时,视图会自动重新渲染。
如果有对象被插入、更新或删除,@FetchRequest 会自动刷新视图。
3、复杂过滤时推荐使用 NSPredicate
predicate 可用于设置过滤条件,例如:
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)],
predicate: NSPredicate(format: "name CONTAINS[cd] %@", "Meeting")
)
var tasks: FetchedResults<Task>
更新 @FetchRequest 数据
1、创建一个新任务
func addTask(context: NSManagedObjectContext) {
// 创建一个新的 Task 对象
let newTask = Task(context: context)
// 设置新任务的属性
newTask.name = "New Task" // 任务名称
newTask.timestamp = Date() // 记录创建时间
// 尝试保存到 Core Data
do {
try context.save() // 将更改提交到 Core Data
} catch {
// 如果发生错误,抛出异常并终止程序
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
1、let newTask = Task(context: context)
通过 NSManagedObjectContext 创建一个 Task 实体实例。
context 是 Core Data 的 viewContext,负责管理数据的更改。
2、设置属性
newTask.name = “New Task”:新建任务的名称是 “New Task”。
newTask.timestamp = Date():将当前时间记录为 timestamp。
3、保存数据
try context.save():尝试将数据保存到 Core Data 持久化存储中。
如果 save() 失败,会触发 catch,然后使用 fatalError() 终止程序并抛出错误信息。
2、删除一个任务
func deleteTask(task: Task, context: NSManagedObjectContext) {
// 从 Core Data 中删除 task 对象
context.delete(task)
// 尝试保存更改
do {
try context.save() // 确保 Core Data 同步更新
} catch {
// 处理错误
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
1、context.delete(task)
通过 context.delete() 方法删除 task 对象。
task 是一个已经存在的 Task 实体实例。
2、保存更改
try context.save():将删除操作提交到 Core Data。
如果 save() 失败,抛出错误并终止程序。
3、使用函数
添加任务:
addTask(context: viewContext)
删除任务:
if let taskToDelete = exchangeRates.first {
deleteTask(task: taskToDelete, context: viewContext)
}
4、注意
context.save() 必须在对数据进行更改(新增、删除、修改)后调用,否则更改不会被保存。
如果 save() 失败,fatalError() 会导致应用崩溃。在生产环境中,应该使用更安全的错误处理机制,比如:
总结
@FetchRequest 是 SwiftUI 中获取 Core Data 数据的便捷工具。
它会监听数据变化,并在 Core Data 更新时自动重新渲染视图。
通过 sortDescriptors 和 predicate 可以灵活排序和过滤数据。
@FetchRequest 需要 managedObjectContext 注入,否则无法正常工作。
如果Core Data在Xcode中预览报错,请参考《Core Data预览报错问题》
相关文章
Core Data预览报错问题:https://fangjunyu.com/2025/03/30/core-data%e9%a2%84%e8%a7%88%e6%8a%a5%e9%94%99%e9%97%ae%e9%a2%98/