我需要将大量的json提要存储到Core Data中。有太多的Feed,我无法一次性调用它们,因为加载应用程序需要很长时间。因此,当应用程序启动时,我会调用最重要的应用程序,并将其余部分分配到整个应用程序中。但是,我还需要将这些存储到Core Data中。
第一个视图只是一个tableview,其中包含名称。当您单击某个名称时,您将被发送到下一个视图,其中应该有一些文本和一些图片。因此,当加载第二个视图时,我向Web服务发送请求并将该服务的答案存储在Core Data中。
如果您单击两次相同的tableviewcell,则所调用的服务中的信息将被写入Core Data两次,从而创建重复值。我想避免这种情况。
我想要做的是检查我的实体是否已包含其中一个唯一值。如果是,请不要存储在Core Data中。如果没有,请存储它。
这是我的方法:
-(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;
}
有没有人知道如何实现这一目标?谓词错了吗?如何检查谓词是否为真?
任何帮助将不胜感激!
答案 0 :(得分:2)
你正在做的事情会非常昂贵。您必须记住,每次执行NSFetchRequest
时,您将执行SQL(昂贵)并执行I / O(也很昂贵)。您的目标是限制您执行此操作的次数。
如果您可以获得(例如10个)唯一键的列表(在您的情况下是imageURL),然后执行获取请求以查看这些imageURL中哪些已经存储在商店中,那将会便宜很多(a在这种情况下,因子约为10)。
此外,由于您对实际对象不感兴趣,只是它们是否存在,您应该将获取请求的resultType
设置为NSDictionaryResultType
并将propertiesToFetch
设置为包含只是你的关键词[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;
}
希望这有帮助。