2009-09-16 56 views
5

我想取一串某种类型的记录,基于由用户定义的类型列表上...iPhone上的CoreData支持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

这应该工作,但我不能为我的生活弄清楚为什么它不是。阅读Predicate Format String Syntax文档并查看是否可以找到任何内容:http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html – Tim 2009-09-16 23:56:23

+0

同意。你可以尝试使用NSArray而不是NSSet,但应该按照书面方式工作。 – 2009-09-17 06:46:22

+2

如果你得到它的工作,你应该标记其中一个答案是正确的。 – 2010-08-10 23:11:46

回答

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。感谢所有这些。 – 2009-09-21 18:52:32

-1

试着改变你的谓词@"ANY type IN %@"

0

嗯。我尝试添加ANY关键字并使用NSArray。事实上,当我从Core Data得到这个异常时,我开始使用NSAArray。回想起来认为,因为我将两个表达式与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

我一直在努力。最终我最终为每个集合做了一个子谓词。

因此,例如:

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