2012-01-11 3 views
1

Мне нужно сохранить большое количество json-каналов в Core Data. Существует так много каналов, что я не могу их сразу вызвать, потому что загрузка приложения слишком долго. Поэтому я называю самые важные из них, когда приложение запускается, и делят остальные на протяжении всего приложения. Тем не менее, мне также нужно хранить их в Core Data.Используйте NSPredicate для проверки того, содержит ли объект уже значение при вставке данных

Первый вид - это просто табличное представление с именами в них. Когда вы нажимаете на имя, вы отправляетесь на следующее представление, где должны быть некоторые тексты и несколько изображений. Поэтому, когда загружается второе представление, я отправляю запрос в веб-службу и сохраняю ответ для службы в Core Data.

Случается, что если вы дважды щелкнете по той же таблице tableview, информация из вызываемой службы будет записана в 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; 
} 

Кто-нибудь есть идея, как я могу добиться этого? Неправильно ли предикат? Как проверить, является ли предикат истинным или нет?

Любая помощь будет оценена!

ответ

2

Что вы делаете, это будет очень дорого. Вы должны помнить, что каждый раз, когда вы выполняете NSFetchRequest, вы собираетесь выполнять SQL (дорого) и делать I/O (также дорого). Ваша цель - ограничить количество раз, когда вы это делаете.

Если вы можете получить список (скажем, 10) уникальных ключей (в вашем случае imageURL), а затем выполнить запрос выборки, чтобы увидеть, какие из этих изображенийURL уже находятся в магазине, это будет намного дешевле (в этом случае коэффициент составляет примерно 10).

Кроме того, так как вы не заинтересованы в реальных объектов, но только существуют ли они, вы должны установить resultType в NSDictionaryResultType и установить 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; 
} 

Надеюсь, что это поможет.