NSManagedObjectContext(简称 context)是 Core Data 的核心对象之一,负责管理应用中的数据生命周期,包括:
创建:向 Core Data 中添加新数据。
读取:从持久化存储中获取数据。
更新:修改数据并保存更改。
删除:删除数据并提交更改。
这里涉及的部分代码和知识,需要查看@FetchRequest的文章《SwiftUI获取Core Data数据的@FetchRequest》。
核心概念
context 是 Core Data 中的临时工作区,类似于一个缓冲区。
对数据的任何更改都会在 context 中暂存,直到调用 save() 才会同步到持久化存储(通常是 SQLite 数据库)。
如果没有显式调用 save(),数据更改不会持久化。
常见场景
1、添加数据
func addTask(context: NSManagedObjectContext) {
let newTask = Task(context: context)
newTask.name = "Learn Core Data"
newTask.timestamp = Date()
do {
try context.save() // 保存更改到数据库
} catch {
print("Error saving task: \(error.localizedDescription)")
}
}
2、读取数据
使用 @FetchRequest 或 NSFetchRequest 从 context 获取数据。
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Task.timestamp, ascending: true)],
animation: .default)
private var tasks: FetchedResults<Task>
3、更新数据
func updateTask(task: Task, context: NSManagedObjectContext) {
task.name = "Updated Task Name"
do {
try context.save() // 保存更新
} catch {
print("Error updating task: \(error.localizedDescription)")
}
}
4、删除数据
func deleteTask(task: Task, context: NSManagedObjectContext) {
context.delete(task)
do {
try context.save() // 删除后保存
} catch {
print("Error deleting task: \(error.localizedDescription)")
}
}
如何创建 NSManagedObjectContext?
1、使用 NSPersistentContainer 获取 viewContext
let container = NSPersistentContainer(name: "MyDataModel")
container.loadPersistentStores { (storeDescription, error) in
if let error = error {
fatalError("Error loading Core Data: \(error)")
}
}
// 获取 `viewContext`
let context = container.viewContext
2、通过 @Environment 传递到视图
@Environment(\.managedObjectContext) private var viewContext
viewContext 和 backgroundContext 的区别
viewContext
主要在主线程中运行。
适用于 UI 相关的操作(如 @FetchRequest)。
在后台线程中运行,避免阻塞主线程。
适合大批量数据导入或异步操作。
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform {
let task = Task(context: backgroundContext)
task.name = "Background Task"
do {
try backgroundContext.save()
} catch {
print("Error saving in background: \(error.localizedDescription)")
}
}
常见方法
1、fetch查询数据库
执行一个 NSFetchRequest 查询数据库,返回对象类型为[NSManagedObject]。
let request = NSFetchRequest<UserForeignCurrency>(entityName: "UserForeignCurrency")
let results = try viewContext.fetch(request)
2、count统计
获取符合查询条件的记录数,返回对象类型为Int。
let request = NSFetchRequest<UserForeignCurrency>(entityName: "UserForeignCurrency")
let count = try viewContext.count(for: request)
3、object对象
通过对象 ID 获取对象,可能尚未加载其属性,返回对象类型为NSManagedObject。
let objectID = someCurrency.objectID
let object = viewContext.object(with: objectID)
4、existingObject对象
和 object(with:) 类似,但如果对象不存在会抛出异常,返回对象类型为NSManagedObject。
let object = try viewContext.existingObject(with: objectID)
5、insert插入对象
通常不直接用,Swift 用法是通过构造函数:
let newCurrency = UserForeignCurrency(context: viewContext)
newCurrency.symbol = "USD"
newCurrency.amount = 123.45
6、delete删除对象
删除某个托管对象。
viewContext.delete(someCurrency)
7、refresh刷新对象状态
刷新对象状态(从数据库重新加载,或者重置为未加载状态)。
viewContext.refresh(someCurrency, mergeChanges: true)
8、rollback回滚
撤销所有未保存的更改。
viewContext.rollback()
9、reset清空
彻底清空上下文(所有未保存对象都会丢失)。
viewContext.reset()
10、save保存
将所有更改保存到数据库。
if viewContext.hasChanges {
try viewContext.save()
}
11、hasChanges是否修改
判断是否有未保存更改。
if viewContext.hasChanges {
// 可以保存
}
12、perform异步执行
在上下文线程异步执行任务。
viewContext.perform {
// 后台安全执行
}
13、performAndWait同步执行
在上下文线程同步执行任务(阻塞当前线程)。
viewContext.performAndWait {
// 同步任务
}
14、mergeChanges合并变更
将另一个上下文的更改合并到当前上下文。
NotificationCenter.default.addObserver(forName: .NSManagedObjectContextDidSave, object: nil, queue: nil) { notification in
viewContext.mergeChanges(fromContextDidSave: notification)
}
15、undoManager撤销管理器
设置或使用撤销管理器。
viewContext.undoManager?.undo()
viewContext.undoManager?.redo()
16、undo/redo/resetUndoManager
手动撤销、重做或undo管理。
17、parent父上下文
当前上下文的父上下文,支持“分层结构”操作。
使用示例
在使用viewContext中,可以搭配NSFetchRequest使用,例如快速查询最新的日期:
func fetchLatestDate() -> Date? {
let request = NSFetchRequest<NSDictionary>(entityName: "Eurofxrefhist")
request.resultType = .dictionaryResultType
request.propertiesToFetch = ["date"]
request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
request.fetchLimit = 1
do {
if let result = try viewContext.fetch(request).first,
let latestDate = result["date"] as? Date {
return latestDate
}
} catch {
print("Error fetching latest date: \(error)")
}
return nil
}
在这段代码中,通过NSFetchRequest<NSDictionary>快速查询最新日期的数据。
通过viewContext.fetch()获取最新数据数组的第一个元素,并解包日期字段获取最新的日期。
最后,Xcode输出的内容为:
Optional(2025-04-10 16:00:00 +0000)
总结
NSManagedObjectContext 负责管理 Core Data 的数据生命周期。
通过 viewContext 处理 UI 数据,通过 backgroundContext 进行后台操作。
确保在数据更改后调用 context.save() 来持久化数据。
相关文章
1、SwiftUI获取Core Data数据的@FetchRequest:https://fangjunyu.com/2025/03/30/swiftui%e8%8e%b7%e5%8f%96core-data%e6%95%b0%e6%8d%ae%e7%9a%84fetchrequest/
2、Core Data管理数据模型的NSPersistentContainer:https://fangjunyu.com/2025/03/29/core-data%e7%ae%a1%e7%90%86%e6%95%b0%e6%8d%ae%e6%a8%a1%e5%9e%8b%e7%9a%84nspersistentcontainer/
3、Core Data NSManagedObjectContext的后台上下文backgroundContext:https://fangjunyu.com/2025/03/31/core-data-nsmanagedobjectcontext%e7%9a%84%e5%90%8e%e5%8f%b0%e4%b8%8a%e4%b8%8b%e6%96%87backgroundcontext/