如何使用 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)")


注意:

我在下面找到了关于executemoc 的评论

在不影响托管对象上下文内容的情况下将请求传递给存储的方法。

这意味着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 时如何解决空间问题?

我如何在单个提取请求中调用两个 NSPredicate。核心数据 iOS Swift

如何设置 NSPredicate 来检查关系的属性?

使用 NSPredicate 比较核心数据查询中的日期