2011-05-24 100 views
8

我經常使用Transformable來處理Core Data attributes,所以我可以在以後更改它們。核心數據可變形屬性不與NSPredicate搭配使用

然而,這似乎是,如果我想使用NSPredicate找到NSManagedObject,使用"uniqueKey == %@",或"uniqueKey MATCHES[cd] %@",它不工作,因爲它應該。

它總是會錯過匹配對象,直到我將匹配對象的uniqueKey的屬性更改爲具有特定類,如NSStringNSNumber

有人可以解釋使用NSPredicateTransformable屬性的限制嗎?

+0

我測試唯一鍵==%@是確定的,和火柴,包含,不一樣的成功。 – user501836 2012-11-20 04:19:07

回答

5

注意:我不知道當/如果因爲5/2011這種情況已經改變(從斯科特Ahten的接受的答案),但你完全可以用NSPredicate搜索關於可變形屬性。斯科特正確地解釋了爲什麼你的假設被打破,但是如果有人可以解釋使用NSPredicate和Transformable屬性的限制嗎?是你的問題,他暗示這是不可能的,那是不正確的。

由於這是第一次谷歌命中「核心數據可轉換值搜索nspredicate」(我試圖尋找靈感尋找),我想補充我的工作答案。

如何使用NSPredicate具有可轉換性質

短,令人興奮的回答:你需要聰明地數據轉換。您需要將該值轉換爲NSData,其中包含我稱之爲「原始標識信息」的內容,即可用於重建對象的最小,最可識別的一組字節。長的答案,...

最重要的考慮:

  • 你有沒有實際的平均使用可變形的特性?如果任何支持的數據類型 - 即使是二進制數據 - 就足夠了,就使用它。
  • 你知道可變屬性實際上是什麼嗎?他們如何打包和從商店打包和打包數據?在Apple的文檔中查看Non-Standard Persistent Attributes
    • 閱讀上述內容後,問:隱藏支持類型「支持屬性」的自定義代碼是否適合您?可能使用該技術。

現在,過去的這些考慮,可轉換的屬性是相當光滑。坦率地說,爲Foo實例編寫一個NSValueTransformer「FooToData」到NSData看起來比編寫大量adhoc自定義代碼更清晰。我還沒有發現Core Data不知道需要使用註冊的NSValueTransformer轉換數據的情況。

要繼續簡單地解決這些問題:

  • 你告訴核心數據使用什麼變壓器?在表格視圖中打開Core Data模型,單擊實體,單擊屬性,加載數據模型檢查器窗格。在「屬性類型:可變形」下,將「名稱」設置爲您的變壓器。
  • 使用默認變壓器(再次參見前面的Apple文檔)或編寫自己的變壓器 - transformedValue:必須返回NSData。
    • NSKeyedUnarchiveFromDataTransformerName是默認的變壓器及可能不足以,也可以繪製有點瞬態實例數據,可以使兩個相似的對象是不同的,當他們是平等的。
  • 轉換的值應該只包含 - 我將調用 - 「原始標識信息」。該商店將比較字節,因此每個字節都會計數。
  • 您也可以在全球註冊您的變壓器。我必須這樣做,因爲我實際上在應用程序的其他地方重複使用它們 - 例如NSString *name = @"FooTrans"; [NSValueTransformer setValueTransformer:[NSClassFromString(name) new] forName:name];

您可能不想使用轉換大量查詢的數據操作 - 例如,主要關鍵信息使用變形金剛的大型進口產品 - yikes!

然後最後,我簡單地使用它來測試NSPredicates模型上的高級對象屬性的相等性 - 例如, 「%K ==%@」 - 它工作正常。我沒有嘗試過各種匹配條款,但如果他們有時候工作,而其他人不工作,我不會感到驚訝。

下面是一個NSURL到NSData變換器的例子。爲什麼不直接存儲字符串?是的,沒關係 - 這是自定義代碼屏蔽存儲屬性的一個好例子。這個例子說明了一個額外的字節被添加到字符串化的URL來記錄它是否是一個文件的URL - 讓我們知道當對象解壓縮時要使用哪些構造函數。

// URLToDataTransformer.h - interface 
extern NSString *const kURLToDataTransformerName; 
@interface URLToDataTransformer : NSValueTransformer 
@end 

...

// URLToDataTransformer.m - implementation 
#import "URLToDataTransformer.h" 
NSString *const kURLToDataTransformerName = @"URLToDataTransformer"; 

@implementation URLToDataTransformer 
+ (Class)transformedValueClass { return [NSData class]; } 
+ (BOOL)allowsReverseTransformation { return YES; } 

- (id)transformedValue:(id)value 
{ 
    if (![value isKindOfClass:[NSURL class]]) 
    { 
     // Log error ... 
     return nil; 
    } 
    NSMutableData *data; 
    char fileType = 0; 
    if ([value isFileURL]) 
    { 
     fileType = 1; 
     data = [NSMutableData dataWithBytes:&fileType length:1]; 
     [data appendData:[[(NSURL *)value path] dataUsingEncoding:NSUTF8StringEncoding]]; 
    } 
    else 
    { 
     fileType = -1; 
     data = [NSMutableData dataWithBytes:&fileType length:1]; 
     [data appendData:[[(NSURL *)value absoluteString] dataUsingEncoding:NSUTF8StringEncoding]]; 
    } 
    return data; 
} 

- (id)reverseTransformedValue:(id)value 
{ 
    if (![value isKindOfClass:[NSData class]]) 
    { 
     // Log error ... 
     return nil; 
    } 

    NSURL *url = nil; 
    NSData *data = (NSData *)value; 
    char fileType = 0; 
    NSRange range = NSMakeRange(1, [data length]-1); 
    [data getBytes:&fileType length:1]; 
    if (1 == fileType) 
    { 
     NSData *actualData = [data subdataWithRange:range]; 
     NSString *str = [[NSString alloc] initWithData:actualData encoding:NSUTF8StringEncoding]; 
     url = [NSURL fileURLWithPath:str]; 
    } 
    else if (-1 == fileType) 
    { 
     NSData *actualData = [data subdataWithRange:range]; 
     NSString *str = [[NSString alloc] initWithData:actualData encoding:NSUTF8StringEncoding]; 
     url = [NSURL URLWithString:str]; 
    } 
    else 
    { 
     // Log error ... 
     return nil; 
    } 

    return url; 
} 
@end 
4

可變形屬性通常作爲歸檔二進制數據持久化。因此,您試圖將NSData的實例與NSString或NSNumber的實例進行比較。

由於這些類以不同的方式解釋相同的數據,因此它們不被認爲是匹配的。

-1

你可以試試這個方法

NSExpression *exprPath = [NSExpression expressionForKeyPath:@"transformable_field"]; 
NSExpression *exprKeyword = [NSExpression expressionForConstantValue:nsdataValue]; 
NSPredicate *predicate = [NSComparisonPredicate predicateWithLeftExpression:exprPath rightExpression:exprKeyword modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0];