ios 核心数据:删除实体的所有实例的最快方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1383598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:23:32  来源:igfitidea点击:

Core Data: Quickest way to delete all instances of an entity

iosobjective-ccore-data

提问by Adaromas

I'm using Core Data to locally persist results from a Web Services call. The web service returns the full object model for, let's say, "Cars" - could be about 2000 of them (and I can't make the Web Service return anything less than 1 or ALL cars.

我正在使用 Core Data 在本地保存来自 Web 服务调用的结果。Web 服务返回完整的对象模型,比如说“汽车”——可能是其中的 2000 辆(我不能让 Web 服务返回少于 1 辆或所有汽车的任何东西。

The next time I open my application, I want to refresh the Core Data persisted copy by calling the Web Service for all Cars again, however to prevent duplicates I would need to purge all data in the local cache first.

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

Is there a quicker way to purge ALL instances of a specific entity in the managed object context (e.g. all entities of type "CAR"), or do I need to query them call, then iterate through the results to delete each, then save?

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

Ideally I could just say delete all where entity is Blah.

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

回答by Dave DeLong

iOS 9 and later:

iOS 9 及更高版本:

iOS 9 added a new class called NSBatchDeleteRequestthat allows you to easily delete objects matching a predicate without having to load them all in to memory. Here's how you'd use it:

iOS 9 添加了一个名为的新类NSBatchDeleteRequest,允许您轻松删除与谓词匹配的对象,而无需将它们全部加载到内存中。以下是您如何使用它:

Swift 5

斯威夫特 5

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

do {
    try myPersistentStoreCoordinator.execute(deleteRequest, with: myContext)
} catch let error as NSError {
    // TODO: handle the error
}

Objective-C

目标-C

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];

NSError *deleteError = nil;
[myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];

More information about batch deletions can be found in the "What's New in Core Data" session from WWDC 2015(starting at ~14:10).

有关批量删除的更多信息,请参见WWDC 2015 的“核心数据新增功能”会议(从 14:10开始)。

iOS 8 and earlier:

iOS 8 及更早版本:

Fetch 'em all and delete 'em all:

全部获取并删除它们:

NSFetchRequest *allCars = [[NSFetchRequest alloc] init];
[allCars setEntity:[NSEntityDescription entityForName:@"Car" inManagedObjectContext:myContext]];
[allCars setIncludesPropertyValues:NO]; //only fetch the managedObjectID

NSError *error = nil;
NSArray *cars = [myContext executeFetchRequest:allCars error:&error];
[allCars release];
//error handling goes here
for (NSManagedObject *car in cars) {
  [myContext deleteObject:car];
}
NSError *saveError = nil;
[myContext save:&saveError];
//more error handling here

回答by roy

Reset Entity in Swift 3:

Swift 3 中重置实体:

func resetAllRecords(in entity : String) // entity = Your_Entity_Name
    {

        let context = ( UIApplication.shared.delegate as! AppDelegate ).persistentContainer.viewContext
        let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
        do
        {
            try context.execute(deleteRequest)
            try context.save()
        }
        catch
        {
            print ("There was an error")
        }
    }

回答by Jon - LBAB

A little bit more cleaned and universal : Add this method :

更干净和通用一点:添加此方法:

- (void)deleteAllEntities:(NSString *)nameEntity
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:nameEntity];
    [fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID

    NSError *error;
    NSArray *fetchedObjects = [theContext executeFetchRequest:fetchRequest error:&error];
    for (NSManagedObject *object in fetchedObjects)
    {
        [theContext deleteObject:object];
    }

    error = nil;
    [theContext save:&error];
}

回答by Gaurav Sharma

For Swift 2.0:

对于 Swift 2.0:

class func clearCoreData(entity:String) {
  let fetchRequest = NSFetchRequest()
  fetchRequest.entity = NSEntityDescription.entityForName(entity, inManagedObjectContext: moc!)
  fetchRequest.includesPropertyValues = false
  do {
    if let results = try moc!.executeFetchRequest(fetchRequest) as? [NSManagedObject] {
      for result in results {
        moc!.deleteObject(result)
      }

      try moc!.save()
    }
  } catch {
    LOG.debug("failed to clear core data")
  }
}

回答by Ixx

Swift:

迅速:

let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
fetchRequest.includesPropertyValues = false

var error:NSError?
if let results = context.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject] {
    for result in results {
        context.deleteObject(result)
    }

    var error:NSError?
    if context.save(&error) {
        // do something after save

    } else if let error = error {
        println(error.userInfo)
    }

} else if let error = error {
    println("error: \(error)")
}

回答by T. Markle

This is a similar question to the one hereand someone suggested setting up a relationship delete rule so you only have to delete one object. So if you have or can make an entity with a to-many relationship to the cars and set the delete rule to cascade when you delete the higher entity all the cars will be deleted as well. This may save some processing time since you don't have to do the steps involved with loading ALL the cars. In a larger data set this could be absolutely necessary.

这是一个与此处类似的问题,有人建议设置关系删除规则,这样您只需删除一个对象。因此,如果您拥有或可以创建一个与汽车具有一对多关系的实体,并在删除更高实体时将删除规则设置为级联,则所有汽车也将被删除。这可能会节省一些处理时间,因为您不必执行加载所有汽车所涉及的步骤。在更大的数据集中,这可能是绝对必要的。

回答by Erhard Dinhobl

A good answer was already posted, this is only a recommendation!

一个好的答案已经发布,这只是一个建议!

A good way would be to just add a category to NSManagedObjectand implement a method like I did:

一个好方法是NSManagedObject像我一样添加一个类别并实现一个方法:

Header File (e.g. NSManagedObject+Ext.h)

头文件(例如NSManagedObject+Ext.h

@interface NSManagedObject (Logic)

+ (void) deleteAllFromEntity:(NSString*) entityName;

@end


Code File: (e.g. NSManagedObject+Ext.m)

代码文件:(例如 NSManagedObject+Ext.m)

@implementation NSManagedObject (Logic)

+ (void) deleteAllFromEntity:(NSString *)entityName {
    NSManagedObjectContext *managedObjectContext = [AppDelegate managedObjectContext];
    NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
    [allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext]];
    [allRecords setIncludesPropertyValues:NO];
    NSError * error = nil;
    NSArray * result = [managedObjectContext executeFetchRequest:allRecords error:&error];
    for (NSManagedObject * profile in result) {
        [managedObjectContext deleteObject:profile];
    }
    NSError *saveError = nil;
    [managedObjectContext save:&saveError];
}

@end

... the only thing you have to is to get the managedObjectContext from the app delegate, or where every you have it in ;)

...您唯一需要做的就是从应用程序委托中获取 managedObjectContext,或者在您拥有它的每个地方获取它;)

afterwards you can use it like:

之后你可以像这样使用它:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

one further optimization could be that you remove the parameter for tha entityname and get the name instead from the clazzname. this would lead to the usage:

进一步的优化可能是您删除实体名称的参数并从 clazzname 获取名称。这将导致使用:

[ClazzName deleteAllFromEntity];


a more clean impl (as category to NSManagedObjectContext):

一个更干净的实现(作为 NSManagedObjectContext 的类别):

@implementation NSManagedObjectContext (Logic)

- (void) deleteAllFromEntity:(NSString *)entityName {
    NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
    [allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:self]];
    [allRecords setIncludesPropertyValues:NO];
    NSError * error = nil;
    NSArray * result = [self executeFetchRequest:allRecords error:&error];
    for (NSManagedObject * profile in result) {
        [self deleteObject:profile];
    }
    NSError *saveError = nil;
    [self save:&saveError];
}

@end

The usage then:

然后的用法:

[managedObjectContext deleteAllFromEntity:@"EntityName"];

回答by Xcodian Solangi

Swift 4, iOS 12 and Xcode 10 Update

Swift 4、iOS 12 和 Xcode 10 更新

100% working just cut & paste

100% 工作只是剪切和粘贴

Just put this function in relevant class and call this function self.deleteData()in viewDidLoad()or anywhere or under a function or a button so that by clicking a button all the data from entity should be deleted and replace the "myEntity" as your entity that you have defined in your core data

只需将此函数放在相关类中,并在函数或按钮self.deleteData()viewDidLoad()或任何地方或下调用此函数,以便通过单击按钮删除实体中的所有数据并将“myEntity”替换为您在您的实体中定义的实体核心数据

func deleteData() {
    let appDel:AppDelegate = (UIApplication.shared.delegate as! AppDelegate)
    let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "myEntity")
    fetchRequest.returnsObjectsAsFaults = false         
    do {
        let results = try context.fetch(fetchRequest)
        for managedObject in results {
            if let managedObjectData: NSManagedObject = managedObject as? NSManagedObject {
                context.delete(managedObjectData)
            }
        }
    } catch let error as NSError {
        print("Deleted all my data in myEntity error : \(error) \(error.userInfo)")
    }
}

回答by Karun Kumar

iOS 10 and later

iOS 10 及更高版本

Works with all versions. Pass entity name and iterate through to delete all the entries and save the context.

适用于所有版本。传递实体名称并遍历以​​删除所有条目并保存上下文。

func deleteData(entityToFetch: String, completion: @escaping(_ returned: Bool) ->()) {
        let context = NSManagedObjectContext()
        context = your managedObjectContext

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
        fetchRequest.entity = NSEntityDescription.entity(forEntityName: entityToFetch, in: context)
        fetchRequest.includesPropertyValues = false
         do {   
            let results = try context.fetch(fetchRequest) as! [NSManagedObject]
            for result in results {
                context.delete(result)
            }
            try context.save()
            completion(true)
        } catch {
            completion(false)
            print("fetch error -\(error.localizedDescription)")
        }
    }

回答by SwiftDeveloper

Swift 3.Xand Swift 4.X, Easy way. Change only YourTable

Swift 3.XSwift 4.X,简单的方法。仅更改YourTable

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