Используйте NSPredicate, чтобы проверить, содержит ли сущность значение при вставке данных. - PullRequest
1 голос
/ 11 января 2012

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

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

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

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

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

1 Ответ

2 голосов
/ 11 января 2012

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

Если вы можете получить список (скажем, 10) уникальных ключей (в вашем случае imageURL), а затем выполнить запрос на выборку, чтобы посмотреть, какие из этих imageURL уже есть в магазине, это будет намного дешевле ( в данном случае примерно 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;
}

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

...