我使用Core Data在本地持久化Web服务调用的结果。web服务返回完整的对象模型,比如说,“Cars”——可能有2000辆车(我不能让web服务返回小于1辆或ALL辆的任何东西。

下次打开应用程序时,我希望通过再次调用所有汽车的Web服务来刷新Core Data持久化副本,但是为了防止重复,我需要首先清除本地缓存中的所有数据。

是否有一种更快的方法来清除管理对象上下文中特定实体的所有实例(例如,类型为“CAR”的所有实体),或者我需要查询它们调用,然后遍历结果删除每个,然后保存?

理想情况下,我可以说删除实体所在的所有地方等等。


当前回答

OOP方式,没有任何字符串作为实体名称 Swift 3+, Xcode 10+

func batchDelete<T>(in context: NSManagedObjectContext, fetchRequest: NSFetchRequest<T>) throws {
    guard let request = fetchRequest as? NSFetchRequest<NSFetchRequestResult> else {
        throw ErrorService.defaultError
    }
    let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: request)
    do {
        try context.execute(batchDeleteRequest)
    } catch {
        throw error
    }
}

然后调用do/catch块

    let fetchRequest: NSFetchRequest<YourEntity> = YourEntity.fetchRequest()
    do {
        let data = try context.fetch(fetchRequest)
        if data.count > 0 {
            try self.batchDelete(in: context, fetchRequest: fetchRequest)
        }
    } catch {
        // throw error
    }

其他回答

当最小iOS为9.0时,使用NSBatchDeleteRequest删除多条记录。如果是后台线程,执行NSManagedObjectContext save,否则使用NSFetchRequest获取记录并删除for循环中的所有记录,删除完成后保存。

快速清除DB中的所有对象:

func purgeAllData() {
    let uniqueNames = persistentContainer.managedObjectModel.entities.compactMap({ $0.name })

    uniqueNames.forEach { (name) in
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: name)
       let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
         do {
        try persistentContainer.viewContext.execute(batchDeleteRequest)
      } catch {
        let nserror = error as NSError
        fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
      }
   }
 }

斯威夫特3。X和Swift 4。X,简单。只改变你的表格

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "YourTable")
    fetchRequest.returnsObjectsAsFaults = false

    do
    {
        let results = try context.fetch(fetchRequest)
        for managedObject in results
        {
            let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
            context.delete(managedObjectData)
        }
    } catch let error as NSError {
        print("Detele all my data in \(entity) error : \(error) \(error.userInfo)")
    }

在Swift 3.0中

 func deleteAllRecords() {
        //delete all data
        let context = appDelegate.persistentContainer.viewContext

        let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "YourClassName")
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)

        do {
            try context.execute(deleteRequest)
            try context.save()
        } catch {
            print ("There was an error")
        }
    }

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)
    }
}