2009-09-16 2 views
5

Я пытаюсь принести кучу записей определенного типа, на основе списка типов, определенных пользователем ...Поддерживает ли CoreData на iPhone предикаты IN?

[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})' 

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

+1

Это должно сработать, но я не могу на всю жизнь понять, почему это не так. Прочитайте документ синтаксиса String формата Predicate и посмотрите, можете ли вы найти что-либо: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html – Tim

+0

Согласовано. Вы можете попробовать NSArray вместо NSSet, но это должно работать как написано. –

+2

Если вы его работаете, вы должны пометить один из ответов как правильный. –

ответ

15

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

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

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

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

Он работает с использованием NSArray, а не NSSet. Спасибо всем за это. –

-1

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

0

Хм. Я попытался добавить ключевое слово ANY и использовать NSArray. На самом деле я использовал NSAArray для начала, когда получил это исключение из Core Data. Оглядываясь назад, я думаю, что, поскольку я сочетал два выражения с И, это было проблемой для 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

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

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

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]];   
}