如何使用 NSPredicate 从 CoreData 中删除选定数量的行?
Posted
技术标签:
【中文标题】如何使用 NSPredicate 从 CoreData 中删除选定数量的行?【英文标题】:How to delete a selected number of rows from CoreData using NSPredicate? 【发布时间】:2013-09-02 20:45:39 【问题描述】:我想从 CoreData 表中删除选定的项目列表:A number of Persons with certain namesToDelete
:
NSError* error = nil;
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Person"
inManagedObjectContext:managedObjectContext]];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"NOT (name IN %@)", namesToDelete];
[request setPredicate:predicate];
NSArray* deleteArray = [managedObjectContext executeFetchRequest:request error:&error];
if (error == nil)
for (NSManagedObject* object in deleteArray)
[managedObjectContext deleteObject:object];
[managedObjectContext save:&error];
//### Error handling.
else
//### Error handling.
这可行,但这是在 CoreData 中执行此操作的最简单/最短的方法吗?
【问题讨论】:
你可以减少几行,但这就是过程。 @Wain 请告诉我如何回答,我会奖励你:-) 【参考方案1】:关于最佳修剪是这样的:
NSError* error = nil;
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
[request setPredicate:[NSPredicate predicateWithFormat:@"NOT (name IN %@)", namesToDelete]];
NSArray* deleteArray = [managedObjectContext executeFetchRequest:request error:&error];
if (deleteArray != nil)
for (NSManagedObject* object in deleteArray)
[managedObjectContext deleteObject:object];
[managedObjectContext save:&error];
//### Error handling.
else
//### Error handling.
还要注意,您检查数组是否作为成功标准返回,而不是nil
中的错误。同样对于save:
,您应该检查返回的BOOL
。
【讨论】:
感谢您,感谢您的快速回复!不幸的是,CoreData 在单行中似乎并不好。 如果您要经常这样做,您可以编写一个实用方法,该方法接受实体名称和谓词并返回一个 BOOL。【参考方案2】:在 ios 9 之前,我们会逐个删除对象,但在 iOS 9.0+ 上,我们可以批量删除它们。
您可以在iOS 9.0+
、macOS 10.11+
、tvOS 9.0+
、watchOS 2.0+
上使用NSBatchDeleteRequest
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (name IN %@)", namesToDelete]];
NSFetchRequest *fetchRequest = [Person fetchRequest];
[fetchRequest setPredicate:predicate];
// Create batch delete request
NSBatchDeleteRequest *deleteReq = [[NSBatchDeleteRequest alloc] initWithFetchRequest:fetchRequest];
deleteReq.resultType = NSBatchDeleteResultTypeCount;
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
,那么该对象将不会被删除。
【讨论】:
由于 iOS 9+ 现在是标准(对于大多数人来说),这应该成为公认的答案。谢谢! @meaning-matters 为 swift 用户添加了 swift 代码 :)【参考方案3】:是的,就是这样。没有类似 SQL 的删除功能。
【讨论】:
感谢您的回答。所以没有任何行可以保存来删除我的“NOT (name IN %@)”排除列表?我不需要使用谓词,只想知道最短的代码。【参考方案4】:这就是我在 Swift 中的使用方式。
func deleteRecentWithId(recentID : String)
let fetchRequest: NSFetchRequest<Recent_Message> = Recent_Message.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "recentUserOrGroupid = %@", recentID)
let request = NSBatchDeleteRequest(fetchRequest: fetchRequest as! NSFetchRequest<NSFetchRequestResult>)
do
try context.execute(request)
try context.save()
catch
print ("There was an error")
只需更改您的表名和谓词条件。 享受!!!
【讨论】:
很高兴知道它对您有帮助!以上是关于如何使用 NSPredicate 从 CoreData 中删除选定数量的行?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 NSPredicate 从 CoreData 中删除选定数量的行?
如何使用 NSFetchedRequest 或 NSPredicate 从实体中选择所有行?
在目标 c 中使用 nspredicate 时如何解决空间问题?