核心数据:DELETE WHERE

时间:2011-11-16 20:45:02

标签: objective-c ios core-data

我知道如何使用NSPredicate执行类似SQL SELECT的操作。如何执行DELETE WHERE之类的操作?我是否必须为每个获取的对象调用[NSManagedObjectContext deleteObject]?感谢

NSError *error;

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:TASK_ENTITY inManagedObjectContext:managedObjectContext]];

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"label LIKE  %@", label];
[request setPredicate:predicate];

NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];

[managedObjectContext deleteObject:[array objectAtIndex:0]];

5 个答案:

答案 0 :(得分:6)

我相信循环返回的数组并调用[NSManagedObjectContext deleteObject:]是“正确”/惯用的方法。它可能看起来效率低下,但请记住,fetch命令实际上并不提取对象的数据,而deleteObject:方法只是标记要删除的对象,当您发送[NSManagedObjectContext save:]时会应用该对象。不知道核心数据的内部我不能告诉你它是否与DELETE WHERE查询一样高效(可能是核心数据在获取内存中有索引的主键,并使用那些)但是根据我的分析经验核心数据应用程序并不比保存新对象或更新对象慢得多。

答案 1 :(得分:1)

您可以使用iOS 9.0+macOS 10.11+tvOS 9.0+watchOS 2.0+

上提供的NSBatchDeleteRequest
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label LIKE  %@", label];
NSFetchRequest *fetchRequest = [TaskEntity fetchRequest];
[fetchRequest setPredicate:predicate];
// Create batch delete request
NSBatchDeleteRequest *deleteReq = [[NSBatchDeleteRequest alloc] initWithFetchRequest:fetchRequest];
NSError *error = nil;
NSBatchDeleteResult *deletedResult = [appDelegate.persistentContainer.viewContext executeRequest:deleteReq error:&error];
if (error) {
  NSLog(@"Unable to delete the data");
}
else {
  NSLog(@"%@ deleted", deleteReq.result);
}

Swift代码(来自上面的链接)

let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee")
fetch.predicate = NSPredicate(format: "terminationDate < %@", NSDate())
let request = NSBatchDeleteRequest(fetchRequest: fetch)

do {
    let result = try moc.execute(request)
} catch {
    fatalError("Failed to execute request: \(error)")
}

注意:

我在下面找到关于execute

moc的评论
  

将请求传递到商店而不影响托管对象上下文内容的方法。

这意味着moc中未保存的任何数据都不会受到影响。即如果您创建/更新了属于删除请求条件且未在save上调用moc的实体,则该对象不会被删除。

答案 2 :(得分:0)

除了使用NSArray方法删除之外,我还没有找到其他方法 (如果有我想知道的话)
如果你真的不想存储数组,你可以嵌套调用将它放在一行上。但是,如果这样做,请验证在出现错误时Fetch的返回值是什么。

  

makeObjectsPerformSelector:
  向数组中的每个对象发送由给定选择器标识的消息,从第一个对象开始并继续通过数组到最后一个对象。
       - (void)makeObjectsPerformSelector:(SEL)aSelector

或者有一个块就是假设更快。

答案 3 :(得分:0)

NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];  [fetchRequest setEntity:[NSEntityDescription entityForName:TASK_ENTITY inManagedObjectContext:managedObjectContext];

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@&#34; label LIKE%@&#34;,label.text]];

NSError * error = nil;

NSArray* results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

if(![results count]==0)
{
   [managedObjectContext deleteObject:[results objectAtIndex:0]];
}
if (![managedObjectContext save:&error]) {
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}

答案 4 :(得分:0)

我刚试过这个并且成功了:

NSError *error = nil;
NSFetchRequest* fetchrequest = [NSFetchRequest fetchRequestWithEntityName:@"EntityName"];
[request setPredicate:[NSPredicate predicateWithFormat:@"attribute == %@", variable]];
NSArray *deleteArray = [context executeFetchRequest:fetchrequest error:&error];

if (deleteArray != nil)
{
    for (NSManagedObject* object in deleteArray)
    {
        [context deleteObject:object];

        //Reload/refresh table or whatever view..
    }

    [context save:&error];
}