Core Data修改大量数据的NSBatchUpdateRequest
Core Data修改大量数据的NSBatchUpdateRequest

Core Data修改大量数据的NSBatchUpdateRequest

NSBatchUpdateRequest 是 Core Data 提供的一种高效操作方式,用于在不加载数据到内存中的前提下,批量更新数据库中的记录。它非常适合处理大量数据更新的场景,例如更改成千上万条记录中的某一个字段,而不想逐个实例化对象进行修改。

为什么用 NSBatchUpdateRequest

正常的更新流程是:

1、用 fetchRequest 查询数据。

2、修改每个 NSManagedObject。

3、调用 save() 保存上下文。

但是这种方式在数据量很大时效率低,内存占用高。

而 NSBatchUpdateRequest 会直接在 SQLite 层修改数据,不经过 Core Data 的对象管理系统,因此:

1、速度更快。

2、内存占用更低。

3、不会触发观察者或自动 UI 刷新。

代码示例

假设有一个实体 Currency,要将所有币种的 amount 设置为 0:

// 1. 创建 FetchRequest(只是为了提取条件)
let fetchRequest: NSFetchRequest<Currency> = Currency.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "amount > %f", 100.0)

// 2. 创建 Batch Update Request
let batchRequest = NSBatchUpdateRequest(entityName: "Currency")
batchRequest.predicate = fetchRequest.predicate // 重用条件
batchRequest.propertiesToUpdate = ["amount": 0.0]
batchRequest.resultType = .updatedObjectsCountResultType

do {
    let result = try viewContext.execute(batchRequest) as? NSBatchUpdateResult
    print("批量更新 \(result?.result ?? 0) 条记录")
} catch {
    print("批量更新失败:\(error)")
}

常用属性

1、entityName:String类型,目标实体名称(初始化时设定)。

2、predicate:NSPredicate?类型,条件筛选器(只更新符合条件的数据)。

3、propertiesToUpdate:[AnyHashable: Any]?类型,要更新的属性和值,键是属性名,值是更新值。

4、resultType:NSBatchUpdateRequestResultType类型,返回结果的类型(见下方)。

5、includesSubentities:Bool(默认 true)类型,是否包含子实体(继承该实体的)。

resultType(结果类型)

resultType 决定了 execute() 返回的内容,枚举值如下:

1、.statusOnlyResultType:无具体数据,仅返回是否成功(默认)。

2、.updatedObjectsCountResultType:NSNumber类型,返回更新的对象数量。

3、.updatedObjectIDsResultType:[NSManagedObjectID]类型,返回更新的对象 ID(需要刷新 UI 时用)。

注意:如果更新后还要刷新 UI,推荐使用 .updatedObjectIDsResultType,然后用 context.refresh(_:mergeChanges:) 来同步数据。

刷新已加载对象(可选)

如果想让 SwiftUI 或其他 UI 及时看到变化,需要使用 NSManagedObjectContext.mergeChanges(fromRemoteContextSave:):

if let objectIDs = result?.result as? [NSManagedObjectID] {
    let changes = [NSUpdatedObjectsKey: objectIDs]
    NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [viewContext])
}

注意事项

1、不会自动更新已加载到内存中的对象(你需要手动刷新或 refetch)。

2、不会触发 NSManagedObjectContext 的 KVO 监听,UI 不会自动刷新。

3、推荐用于后台处理或数据迁移等不需要立即刷新 UI 的情况。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注