iPhone上的CoreData是否支持IN谓词?

时间:2009-09-16 23:30:08

标签: iphone sqlite core-data

我正在尝试根据用户定义的类型列表获取一堆特定类型的记录......

[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 个答案:

答案 0 :(得分:15)

我相信Alex是正确的,你必须使用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级别捕获它,从而使错误更清楚。

答案 1 :(得分: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]];

这适合我。

答案 2 :(得分: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]];         
}

答案 3 :(得分:-1)

尝试将谓词更改为@"ANY type IN %@"