2009-09-16 86 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]];   
}