2009-10-21 6 views
10

私はかなり単純なデータモデルを持つCore Dataアプリケーションを持っています。スペースを節約するために、永続ストアにNSImageのインスタンスをPNGビットマップNSDataオブジェクトとして格納できるようにしたいと考えています。変換可能なコアデータ属性がカスタムNSValueTransformerを使用しないのはなぜですか?

この目的のために、単純なNSValueTransformerを記述して、NSImageをPNGビットマップ形式のNSDataに変換しました。私は私のアプリデリゲートにこのコードの値変換を登録しています:

+ (void)initialize 
{ 
    [NSValueTransformer setValueTransformer:[[PNGDataValueTransformer alloc] init] forName:@"PNGDataValueTransformer"]; 
} 

私のデータモデルでは、私が変換可能で画像の属性を設定し、値の変圧器名としてPNGDataValueTransformerを指定しています。

ただし、私のカスタム値トランスフォーマは使用されていません。バリュー・トランスフォーマーの-transformedValue:-reverseTransformedValueのログ・メッセージが記録されていないため、ディスクに保存されているデータはアーカイブされたNSImageであり、PNG NSDataオブジェクトではありません。

なぜこれが機能しないのですか?ここで

は私の価値変圧器のコードです:

@implementation PNGDataValueTransformer 

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

+ (BOOL)allowsReverseTransformation 
{ 
    return YES; 
} 

- (id)transformedValue:(id)value 
{ 
    if (value == nil) return nil; 
    if(NSIsControllerMarker(value)) 
     return value; 
    //check if the value is NSData 
    if(![value isKindOfClass:[NSData class]]) 
    { 
     [NSException raise:NSInternalInconsistencyException format:@"Value (%@) is not an NSData instance", [value class]]; 
    } 
    return [[[NSImage alloc] initWithData:value] autorelease]; 
} 

- (id)reverseTransformedValue:(id)value; 
{ 
    if (value == nil) return nil; 
    if(NSIsControllerMarker(value)) 
     return value; 
    //check if the value is an NSImage 
    if(![value isKindOfClass:[NSImage class]]) 
    { 
     [NSException raise:NSInternalInconsistencyException format:@"Value (%@) is not an NSImage instance", [value class]]; 
    } 
    // convert the NSImage into a raster representation. 
    NSBitmapImageRep* bitmap = [NSBitmapImageRep imageRepWithData: [(NSImage*) value TIFFRepresentation]]; 
    // convert the bitmap raster representation into a PNG data stream 
    NSDictionary* pngProperties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:NSImageInterlaced]; 
    // return the png encoded data 
    NSData* pngData    = [bitmap representationUsingType:NSPNGFileType properties:pngProperties]; 
    return pngData; 
} 

@end 

答えて

0

あなたのコードで何も他の場所で明示的にPNGDataValueTransformerクラスを使用しない場合は、そのクラスの+初期化メソッドが呼び出されることはありません。コアデータモデルの名前を指定してもトリガーされません。その名前のトランスフォーマーインスタンスがまだ登録されていないため、その名前のバリュートランスフォーマーを検索するだけです。

実際にあなたのケースで起こっている場合は、データモデルにアクセスする前にコードのどこかで[PNGDataValueTransformer initialize]の呼び出しを追加するだけです。どんなクラスの+初期化メソッドでも、このデータモデルを使用しています。これにより、コアデータが必要な時にアクセスできるように、バリュートランスフォーマのインスタンスが作成され、登録されます。

+0

こんにちはブライアン、 '+ initialize'方法私のアプリデリゲートではなく、値変換であると私は間違いなくそれを確認することができますそれは呼ばれている。私のNSValueTransformerの '-init'メソッドにブレークポイントを置くと、確実に初期化されます。 属性を「バイナリ」タイプに設定し、IBの各バインディングにバリュートランスを適用すると、正常に動作します。属性型をTransformableとして指定すると、なぜカスタムトランスフォーマーが使用されていないのか分かりません。 –

25

私が間違っていないと、バリュートランスフォーマの向きが逆になります。

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

+ (BOOL)allowsReverseTransformation 
{ 
return YES; 
} 

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

// I pass in raw data when generating the image, save that directly to the database 
if ([value isKindOfClass:[NSData class]]) 
    return value; 

return UIImagePNGRepresentation((UIImage *)value); 
} 

- (id)reverseTransformedValue:(id)value 
{ 
return [UIImage imageWithData:(NSData *)value]; 
} 

これはiPhoneのためですが、あなたは適切な場所であなたのNSImageではコードに交換することができる必要があります:私は、次のようなコードを使用して、自分のアプリケーションで同じことを行います。 Macの実装をまだテストしていないだけです。

私がこれを有効にしたのは、データモデル内で変換可能なイメージプロパティを設定し、トランスの名前を指定することでした。私はあなたの+ initializeメソッドのように、バリュートランスを手動で登録する必要はありませんでした。

+0

Bradに感謝します。私はこれを試して、それは何の違いはありません、私のバリュートランスは無視されます。 –

2

変圧器を登録することは、コアデータがそれを使用するかどうかには影響しません。 私はPhotoLocationsのサンプルコードを使用していましたが、トランスの登録を削除しても効果はありません。あなたのValueTransformerNameがあなたのクラスの名前で、変圧器の実装がターゲットに含まれている限り、動作するはずです。

トランスにコード実行がない場合、トランスのコードは無関係です。この問題は、コアデータスタックのどこか、またはトランスの宣言のどこかにある必要があります。

+0

同じです!あなたは解決策を見つけましたか? – webmastx

0

例コードhereをご覧ください。

これは必要な操作ですか?

1

あなたが明示的に実行時に、あなたの変圧器を登録する必要があります。

NSManagedObjectエンティティサブクラスのClass initializeメソッドをオーバーライドするのが適切です。前述のように、それは既知のコアデータバグです。 Appleの場所のコードサンプルからの重要なコードを以下に示し、それはテストされ、動作します: http://developer.apple.com/library/ios/#samplecode/Locations/Introduction/Intro.html

+ (void)initialize { 
    if (self == [Event class]) { 
     UIImageToDataTransformer *transformer = [[UIImageToDataTransformer alloc] init]; 
     [NSValueTransformer setValueTransformer:transformer forName:@"UIImageToDataTransformer"]; 
    } 
} 
+0

はい、私はこれを知っており、私はそれをやっています。 –

+0

私の場合、それはまさに問題でした。また、トランスフォーマ名がデータモデルで宣言したトランスフォーム名と一致するかどうか、およびトランスフォームされたメソッドのボディを逆変換しなかったかどうかを確認することもできます:transformedValueおよびreverseTransformedValue。 – Lukasz

関連する問題