2010-05-21 96 views
2

我試圖在由sqlite數據庫支持的核心數據存儲中存儲PNG圖像。由於我打算在iPhone上使用此數據庫,因此無法直接存儲NSImage對象。我想使用綁定和NSValueTransformer子類來處理從NSImage(通過我的GUI上的Image well獲得)轉換爲包含圖像的PNG二進制表示的NSData的轉碼。我寫了下面的代碼爲NSValueTransformer核心數據,綁定,值轉換器:保存時崩潰


+ (Class)transformedValueClass 
{ 
    return [NSImage class]; 
} 

+ (BOOL)allowsReverseTransformation 
{ 
    return YES; 
} 

- (id)transformedValue:(id)value 
{ 
    if (value == nil) return nil; 

    return [[[NSImage alloc] initWithData:value] autorelease]; 
} 

- (id)reverseTransformedValue:(id)value 
{ 
    if (value == nil) return nil; 

if(![value isKindOfClass:[NSImage class]]) 
{ 
    NSLog(@"Type mismatch. Expecting NSImage"); 
} 

NSBitmapImageRep *bits = [[value representations] objectAtIndex: 0]; 

NSData *data = [bits representationUsingType:NSPNGFileType properties:nil]; 

    return data; 
} 

該模型具有此NSValueTransformer配置變形特性。在Interface Builder中,表格列和圖像井都綁定到該屬性,並且都具有正確的值轉換器名稱(圖像中放置的圖像很好地顯示在表格列中)。每次添加圖像或重新載入行時都會註冊並調用轉換器(使用NSLog()調用進行檢查)。當我試圖保存管理對象時,問題就出現了。控制檯輸出顯示錯誤消息:

[NSImage中長度]:無法識別的選擇發送到實例0x1004933a0

好像核心數據使用值變壓器,以獲得NSImage背面從NSData和然後嘗試保存NSImage而不是NSData

有可能的解決方法,如在this post中提出的解決方法,但我真的想明白爲什麼我的方法是瑕疵。

在此先感謝您的想法和解釋。

回答

1

我最終得到它的工作(最好睡上它)。有兩個問題。第一個是我在IB綁定和核心數據模型中都指定了相同的值轉換器,這是多餘的。

我的理解是,IB綁定指定值轉換器實際上在視圖和控制器之間轉換值,而核心數據值轉換器充當管理對象和持久存儲之間的中間人。

爲了讓事情變得更糟,第二個問題是我的價值變壓器倒過來。在保存對象(管理對象 - >存儲)時發送transformValue消息,並且在從存儲中加載值時發送reverseTransformedValue,這與將視圖對象綁定到模型對象時使用的轉換器的方向相反。我得到了暗示從core data programming guide在那裏你可以閱讀下面的略帶神祕的注意事項:

要點:雖然默認變壓器是NSKeyedUnarchiveFromDataTransformerName指定的變壓器,該變壓器在反向實際使用。如果明確指定默認的變壓器,核心數據會用它「錯誤的方向」。

即使我的程序工作,到目前爲止,我想有從別人的確認與核心數據的經驗,我會非常感謝您能否指出我可能錯過的一些關於此事的文檔。

在此先感謝。

工作代碼:


+ (Class)transformedValueClass 
{ 
    return [NSData class]; 
} 

+ (BOOL)allowsReverseTransformation 
{ 
    return YES; 
} 

- (id)reverseTransformedValue:(id)value 
{ 
    if (value == nil) return nil; 

    return [[[NSImage alloc] initWithData:value] autorelease]; 
} 

- (id)transformedValue:(id)value 
{ 
    if (value == nil) return nil; 

    if(![value isKindOfClass:[NSImage class]]) 
    { 
     NSLog(@"Type mismatch. Expecting NSImage"); 
    } 

    NSBitmapImageRep *bits = [[value representations] objectAtIndex: 0]; 

    NSData *data = [bits representationUsingType:NSPNGFileType properties:nil]; 

    return data; 
} 

+0

我沒有指定變壓器兩次,並得到相同的錯誤。顛倒transformedValue:和reverseTransformedValue:取得了訣竅。非常感謝! – MartinW 2014-11-05 15:06:23

1

在transformedValue:你直接從NSData到NSImage,但在reverseTransformedValue:你從NSImage到NSBitmapImageRep到NSData。所以他們不一起工作,因爲他們使用不同的方法。模型中的數據實際上是NSBitmapImageRep數據而不是NSImage數據。這兩者需要彼此完全相反。

順便說一下,我最近在另一篇文章中發佈了一個變壓器。你可以看到它here。當然你根本不需要定製變壓器,因爲你可以使用NSKeyedArchiver。 NSImage遵守NSCoder協議,因此它會爲您處理轉換。

+0

謝謝您的回答,我在寫作的同時我自己的答案,所以我錯過了你的。這將訣竅,雖然我真的需要存儲PNG表示,因爲iPhone SDK使用UIImage而不是NSImage。簡單的無變壓器解決方案適用於mac,但在iPhone上讀取sqlite數據庫時會中斷。 – Gael 2010-05-22 08:24:29

+0

是的,我自己使用了一個自定義轉換器,因爲我想在將圖像存儲在覈心數據中之前將圖像大小調整爲較小。我允許某人將圖像拖到圖像上,因此可能會添加大圖像,並且我不想存儲這麼大的圖像...因此我的變壓器(儘管我刪除了在張貼的變壓器中調整大小的圖像) 。 – regulus6633 2010-05-22 08:31:07