我使用Core Data在本地持久化Web服务调用的结果。web服务返回完整的对象模型,比如说,“Cars”——可能有2000辆车(我不能让web服务返回小于1辆或ALL辆的任何东西。
下次打开应用程序时,我希望通过再次调用所有汽车的Web服务来刷新Core Data持久化副本,但是为了防止重复,我需要首先清除本地缓存中的所有数据。
是否有一种更快的方法来清除管理对象上下文中特定实体的所有实例(例如,类型为“CAR”的所有实体),或者我需要查询它们调用,然后遍历结果删除每个,然后保存?
理想情况下,我可以说删除实体所在的所有地方等等。
NSBatchDeleteRequest Swift 5.5和Xcode 13.2
删除SQLite持久存储中的对象,而不加载到内存中。在持久存储上执行的更改不会反映在当前内存中的对象中。
执行批量删除之后,从持久存储中删除内存中的所有对象。
下面是执行batchDeleteRequest的一些方便的扩展方法
extension NSManagedObject {
private static var entityName: String {
return String(describing: self)
}
static func fetchRequest<Self>(
with predicate: NSPredicate? = nil,
configureBlock: ((NSFetchRequest<Self>) -> Void)? = nil
) -> NSFetchRequest<Self> where Self: NSFetchRequestResult {
let request = NSFetchRequest<Self>(entityName: entityName)
request.predicate = predicate
configureBlock?(request)
return request
}
static func batchDelete(with fetchRequest: NSFetchRequest<NSFetchRequestResult>,
in context: NSManagedObjectContext) {
let batchDeteleRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
batchDeteleRequest.resultType = .resultTypeObjectIDs
do {
if let fetchResult = try context.execute(batchDeteleRequest) as? NSBatchDeleteResult,
let deletedManagedObjectIds = fetchResult.result as? [NSManagedObjectID], !deletedManagedObjectIds.isEmpty {
let changes = [NSDeletedObjectsKey: deletedManagedObjectIds]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
}
} catch {
print("Error while executing batchDeleteRequest: \(error.localizedDescription)")
}
}
}
示例:我们可以通过传递fetchRequest调用batchDelete静态方法批量删除实体
class Entity: NSManagedObject {
@NSManaged var name: String?
@NSManaged var value: String?
}
extension Entity {
static func executeBatchDelete(in context: NSManagedObjectContext) {
let predicate = NSPredicate(format: "\(#keyPath(Entity.value)) == %@)", "abc")
let deleteRequest: NSFetchRequest<NSFetchRequestResult> = Entity.fetchRequest(with: predicate)
Entity.batchDelete(with: deleteRequest, in: context)
}
}