2012-01-11 42 views
1

我需要存储大量的JSON送入核心数据时,已经包含了价值。 Feed太多,我无法一次全部打电话给他们,因为应用加载需要很长时间。所以我会在应用程序启动时调用最重要的应用程序,并将其余的应用程序分开。但是,我还需要将这些商店存储到Core Data中。使用NSPredicate来检查,如果实体插入数据

第一种观点只是一个tableview中,在他们的名字。当你点击一个名字时,你会被发送到下一个视图,其中应该有一些文字和几张图片。因此,当第二个视图加载时,我向Web服务发送请求并将服务的答案存储在Core Data中。

会发生什么情况是,如果你点击两次相同tableviewcell,从所谓的服务信息将被写入到核心数据的两倍,创建重复的值。我想避免这种情况。

我想要做的是检查,如果我的实体已经包含了独特的价值之一。如果确实如此,则不要存储在核心数据中。如果没有,存储它。

这里是我的方法:

-(void)addImage:(NSManagedObjectContext *)context withImageUrl:(NSString *)imageUrl{ 
NSFetchedResultsController *fetchedResultsController = [self fetchObjectsFromEntity:@"Image" withContext:context andSortKey:@"imageUrl"]; 

[fetchedResultsController.fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"imageUrl contains[cd] %@" , imageUrl]]; 


if (//WHAT TO PUT HERE?) { 
    NSLog(@"Doesn't exist"); 
    Image *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:context]; 
    image.imageUrl = imageUrl; 
}else{ 
    NSLog(@"Already exists"); 
} 


-(NSFetchedResultsController *)fetchObjectsFromEntity:(NSString *)entityName withContext:(NSManagedObjectContext *)context andSortKey:(NSString *)key{ 
NSError *error; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

if (key != nil) { 

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:key ascending:YES]; 
    NSArray *sortDescs = [[NSArray alloc]initWithObjects:sortDescriptor, nil]; 
    [fetchRequest setSortDescriptors:sortDescs]; 
} 

NSFetchedResultsController *fetchedResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Root"]; 

if (![fetchedResultController performFetch:&error]) { 
    NSLog(@"Error: %@" , error); 
}   

    return fetchedResultController; 
} 

任何人不会有我如何能够做到这一点的想法?谓词错了吗?如何检查谓词是否为真?

任何帮助,将不胜感激!

回答

2

你在做什么将是非常昂贵的。你要记住,每次执行NSFetchRequest你要执行SQL(贵),做I/O(还贵)。你的目标是限制你这样做的次数。

如果你可以得到一个(比如说10个)唯一键(在你的例子中是imageURL)的列表,然后执行获取请求来查看这些imageURL中哪些已经存在,那将会便宜得多在这种情况下约为10倍)。

而且,由于你不感兴趣,在实际的对象,而只是他们是否存在,你应该设置读取请求的resultTypeNSDictionaryResultType并设置propertiesToFetch到一个数组只包含您keym即[NSArray arrayWithObject:@"imageUrl"]

最后,比较字符串是非常昂贵的。尽量不要使用@"imageUrl contains[cd] %@"。它要求数据库做很多工作。如果您有一些数字键,例如一个64位的数字,这会让事情变得更快,因为你可以使用数字比较。

把所有这些放在一起,让我们假设你的唯一键属性被称为uniqueID。你可以运行这样的提取请求

- (NSArray *)keysMissingInStoreFromKeys:(NSArray *)someKeys; 
{ 
    NSFetchRequest *r = [NSFetchRequest fetchRequestWithEntityName:@"Image"]; 
    [r setResultType:NSDictionaryResultType]; 
    [r setPropertiesToFetch:[NSArray arrayWithObject:@"uniqueID"]; 
    NSPredicate *p = [NSPredicate predicateWithFormat:@"uniqueID IN %@", someKeys]; 
    [r setPredicate:p]; 
    NSError *error = nil; 
    NSArray *result = [moc executeFetchRequest:r error:&error]; 
    NSAssert(result != nil, @"Fetch failed: %@", error); 
    NSMutableArray *missingKeys = [someKeys mutableCopy]; 
    for (NSDictionary *values in result) { 
     id uniqueID = [values objectForKey:@"uniqueID"]; 
     [missingKeys removeObject:uniqueID]; 
    } 
    return missingKeys; 
} 

希望这会有所帮助。

相关问题