核心数据:DELETE WHERE
Posted
技术标签:
【中文标题】核心数据:DELETE WHERE【英文标题】:Core Data: DELETE WHERE 【发布时间】:2011-11-16 20:45:01 【问题描述】:我知道如何使用 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]];
【问题讨论】:
我添加了使用可以批量删除对象的新 API (ios 9.0+) 的答案:***.com/a/43388746/468724 【参考方案1】:我相信循环返回的数组并调用[NSManagedObjectContext deleteObject:]
是“正确”/惯用的方法。这可能看起来效率低下,但请记住,fetch 命令实际上并不获取对象的数据,deleteObject:
方法只是将对象标记为删除,当您发送[NSManagedObjectContext save:]
时会应用该对象。不知道 Core Data 的内部结构,我无法告诉您它是否与 DELETE WHERE
查询一样高效(可能 Core Data 在内存中具有从获取中获取的索引主键,并使用这些主键),但根据我对 Core Data 进行分析的经验应用它并不比保存新的或更新的对象慢很多。
【讨论】:
【参考方案2】:您可以在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
中任何未保存的数据都不会受到影响。即,如果您创建/更新了符合删除请求标准的实体,并且没有在 moc
上调用 save
,那么该对象将不会被删除。
【讨论】:
【参考方案3】:除了使用NSArray 删除方法外,我还没有找到其他方法。 (如果有我想知道的) 如果您真的不想存储数组,则可以将调用嵌套在一行上。但是,如果您这样做,请验证在发生错误时 Fetch 的返回值是什么。
makeObjectsPerformSelector: 向数组中的每个对象发送由给定选择器标识的消息,从第一个对象开始,然后通过数组一直到最后一个对象。 - (void)makeObjectsPerformSelector:(SEL)aSelector
或者有一个块可以更快。
【讨论】:
【参考方案4】:我刚刚试了一下,成功了:
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];
【讨论】:
【参考方案5】:NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:TASK_ENTITY inManagedObjectContext:managedObjectContext];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"label LIKE%@", 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]);
【讨论】:
以上是关于核心数据:DELETE WHERE的主要内容,如果未能解决你的问题,请参考以下文章