Поддерживает ли CoreData на iPhone предикаты IN? - PullRequest
5 голосов
/ 17 сентября 2009

Я пытаюсь получить набор записей определенного типа, основываясь на списке типов, определенных пользователем ...

[fetchRequest setEntity:[NSEntityDescription entityForName:@"myRecord" inManagedObjectContext:self.managedObjectContext]];  
NSSet   *shipTypes = [NSSet setWithObjects:[NSNumber numberWithInt:70],
                    [NSNumber numberWithInt:71],
                    [NSNumber numberWithInt:72],
                    [NSNumber numberWithInt:73],
                    [NSNumber numberWithInt:74],
                     nil];
NSPredicate *aPredicate = [NSPredicate predicateWithFormat:@"type in %@", shipTypes];
[fetchRequest setPredicate:aPredicate];
theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

… при запуске сообщение executeFetchRequest выдает исключение…

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unimplemented SQL generation for predicate : (type IN {71, 73, 70, 72, 74})'

Я что-то сделал не так, или это действительно не поддерживается?

Ответы [ 4 ]

15 голосов
/ 20 сентября 2009

Полагаю, Алекс прав, что вам нужно использовать NSArray, хотя, очевидно, было бы лучше, если бы здесь был принят NSSet, поскольку порядок не так важен (хотя это могло бы повлиять на скорость выполнения SQL).

В качестве примечания, я никогда не использую вызов + ПредикатВитФормат: в любом коде, потому что он не может выполнять проверку времени компиляции или проверку типов. Я настоятельно советую использовать индивидуальные занятия.

В этом случае я бы сделал:

fetchRequest.entity = [NSEntityDescription entityForName:@"myRecord" inManagedObjectContext:self.managedObjectContext]];

NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
                                        [NSNumber numberWithInt:71],
                                        [NSNumber numberWithInt:72],
                                        [NSNumber numberWithInt:73],
                                        [NSNumber numberWithInt:74],
                                         nil];
fetchRequest.predicate = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"type"] rightExpression:[NSExpression expressionForConstantValue:shipTypes] modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0];

theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

Не то чтобы это могло отловить эту конкретную ошибку во время компиляции, но она потенциально могла бы отловить ее на уровне NSExpression, что сделало бы ее более ясной, что пошло не так.

0 голосов
/ 03 марта 2011

Я боролся с этим. В конце концов я сделал предикат для каждого набора.

Так, например:

NSMutableArray *subpredicates = [NSMutableArray array];

NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
                                    [NSNumber numberWithInt:71],
                                    [NSNumber numberWithInt:72],
                                    [NSNumber numberWithInt:73],
                                    [NSNumber numberWithInt:74],
                                     nil];

for (NSNumber *num in shipTypes) {
    [subpredicates addObject:[NSPredicate predicateWithFormat:@"ANY type == %@", num]];         
}

NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];

Предполагается, что тип является NSSet. Если это не так, вы можете просто:

for (NSNumber *num in shipTypes) {
    [subpredicates addObject:[NSPredicate predicateWithFormat:@"type == %@", num]];         
}
0 голосов
/ 02 марта 2011

Хм. Я попытался добавить любое ключевое слово и использовать NSArray. На самом деле я использовал NSAArray для начала, когда получил это исключение из Core Data. Оглядываясь назад, я думаю, что поскольку я комбинировал два выражения с AND, это была проблема для Core Data. (Я знаю, что должен вернуться и проверить это, но эта мысль пришла мне в голову, когда я читал этот пост.) Вот мое первоначальное выражение:

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"BPM BETWEEN { %d, %d } AND GENRE IN %@", lower, upper, genres];

Мое решение состояло в том, чтобы разбить его на две части. Теперь я выполняю запрос для BPM с использованием предиката, но я беру полученный массив и использую -filteredArrayUsingPredicate с @ "genre IN% @". Таким образом:

array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"genre IN %@", genres]];

Это работает для меня.

0 голосов
/ 10 августа 2010

Попробуйте изменить предикат на @"ANY type IN %@"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...