核心数据,如何有效地查找和删除托管对象

时间:2014-01-10 17:14:35

标签: ios core-data nspredicate nsmanagedobject

我的应用程序向具有日期(上次更新日期)的服务器发送获取请求以更新其内容(核心数据中的2个实体,没有关系,所有属性都是字符串)...大部分时间它只接收新内容,但有时它也会收到需要更新而不是仅插入的旧内容。 1表非常简单我只是获取将在数组中更新的项的ID(来自服务器的id而不是形成核心数据)并且我获取这些项然后删除它们。之后,我插入更新的项目,因为它们是新的。这是我删除它们的方式:

-(void)deleteOfEntity:(NSString*)entityName theItemsWithIds:(NSArray*)ids{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext: [self managedObjectContext]];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesPropertyValues:NO];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"(id IN %@)", ids]];
NSError *error;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if(fetchedObjects && [fetchedObjects count]>0){
    for (NSManagedObject* toDelete in fetchedObjects) {
        [[self managedObjectContext] deleteObject:toDelete];
    }
}

}

因为标识每个项目的属性名称通常是ID。但是另一个表需要2个属性来标识项目,比如复合键。如何构建“ID”数组?一个数组有2个值的数组,表示复合键?和谓词?我只是想知道是否可以有效地执行此操作,如果不是,我可以随时获取所有项目并逐个检查,但为此我需要for在另一个for内,这是丑陋。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

设计数据库时,您应该创建一个唯一的键字段,即使它只是两个值的组合。那会让这个问题消失。

但是,要解决此问题,您需要对一个类似于上面的键进行提取,然后遍历第二个键。但是,您不需要在循环内执行循环。您可以对返回的数组使用第二个NSPredicate来获取要修改的对象。

不那么丑陋且效率很高,因为你只去了一次磁盘而第二个过滤器正在内存中发生。

更新

@DuncanGroenwald是正确的,你仍然必须遍历每个对象,但是有循环并且有循环。

编写for循环然后在for循环内部进行字符串比较的开发人员使框架执行相同选项的效率明显降低。怎么样?对阵列使用NSPredicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"someValue IN %@", idArray];
NSArray *results = [origArray filteredArrayWithPredicate:predicate];

如果您测试这两个选项,谓词的运行速度会明显加快。

答案 1 :(得分:0)

我所做的就是创建一个名为“identifier”的另一个属性stringWithFormat:@"%@%@",key1,key2,它与coredata中的额外字符串无关,因为它假设该实体中只有几个托管对象