2009-10-21 11 views
10

Oldukça basit bir veri modeline sahip bir Core Data uygulamasına sahibim. Yerimi korumak için kalıcı depodaki PNG Bitmap NSData nesneleri olarak NSImage örneklerini depolayabilmek istiyorum.Dönüştürülebilir Temel Veri özniteliğim neden özel NSValueTransformer kullanmıyor?

Bu amaçla, PNG bitmap biçiminde bir NSImage'ı NSData'ya dönüştürmek için basit bir NSValueTransformer yazdım. Benim App temsilci bu kodla değer trafo kayıt ediyorum:

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

benim veri modelinde, ben Transformable olmaya görüntü özelliğini ayarlayın ve değer trafo adı olarak PNGDataValueTransformer belirttiniz.

Ancak, özel değer dönüştürücüm kullanılmıyor. Günlük trafolarımın -transformedValue: ve -reverseTransformedValue yöntemlerinde günlüğe kaydedilmediğinden ve diske kaydedilmekte olan veriler sadece olması gereken PNG NSData nesnesinden ziyade arşivlenmiş bir NSImage olduğu için bunu biliyorum.

Bu neden çalışmıyor?

@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 

cevap

0

Kodunuzdaki şey başka yerde explicity o sınıf denilen asla, sonra + yöntemi başlatmak PNGDataValueTransformer sınıfını kullanıyorsa: Burada

benim değer trafonun kodudur. Çekirdek Veri modelinizdeki adın belirtilmesi, onu tetiklemeyecektir - yalnızca, bu adla ilgili bir transformatör örneğinin henüz kaydedilmediği için, bu ad için bir değer trafosu aramayı deneyecektir.

Durumunuzda gerçekten böyle bir durum varsa, veri modelinize erişilmeden önce kodunuzda bir yerde [PNGDataValueTransformer initialize] öğesine bir çağrı ekleyin; Bu veri modelini kullanan sınıfın her hangi bir + initialize yönteminde. Bu, Core Data'nın ihtiyaç duyulduğunda erişebilmesi için oluşturulup kaydedilen değer trafo vakasını tetiklemelidir.

+0

Merhaba Brian, '+ initialize' yöntem benim app temsilci değil, değer trafo ve kesinlikle doğrulayabilirsiniz çağrılıyor. NSValueTransformer'imin '-init 'yöntemine bir kesme noktası koyarsam, kesinlikle başlatılır. Özniteliği "binary" türünde olacak şekilde ayarlıyorum ve IB'deki her bir bağlamaya benim değer dönüştürücümü uygularsam, iyi çalışır. Özellik türünü Dönüştürülebilir olarak belirttiğimde neden özel transformatörün kullanılmadığını anlamıyorum. –

25

Yanılmıyorsam, değer dönüştürücünüzün tersi bir yönü vardır. Aşağıdaki gibi bir kod kullanarak, benim uygulamada aynı şeyi yapmak: Bu iPhone için olsa

+ (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]; 
} 

, uygun yerlerde senin NSImage kodunda takas gerekir. Mac uygulamamı henüz test etmedim.

Tüm bunu etkinleştirmek için görüntü özelliğimi veri modeli içinde dönüştürülebilir olacak şekilde ayarlamak ve transformatörün adını belirtmek. + Initialize yönteminde yaptığınız gibi, değer trafosunu manuel olarak kaydetmem gerekmedi.

+0

Teşekkürler Brad. Bunu denedim ve fark yaratmadı, değer transformatörüm göz ardı edildi. –

2

Bu, transformatörün Core Data kullanıp kullanmayacağı üzerinde hiçbir etkisi olmadığını kaydetmiş gibi görünüyor. PhotoLocations örnek kodunda oynatıyorum ve transformatör kaydının kaldırılmasının bir etkisi yok. ValueTransformerName'niz sınıfınızın adı olduğu ve transformatörünüzün uygulamasının hedefe dahil olduğu sürece çalışmalıdır.

Transformatörde kod çalıştırma yoksa, transformatördeki kod ilgisizdir. Sorun, çekirdek veri yığında veya transformatörün beyanında başka bir yerde olmalıdır.

+0

Aynı burada! bir çözüm buldun mu? – webmastx

0

Örnek koduna bakın here.

İstediğinizi yapar mı?

@implementation UIImageToDataTransformer 


+ (BOOL)allowsReverseTransformation { 
    return YES; 
} 

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


- (id)transformedValue:(id)value { 
    NSData *data = UIImagePNGRepresentation(value); 
    return data; 
} 


- (id)reverseTransformedValue:(id)value { 
    UIImage *uiImage = [[UIImage alloc] initWithData:value]; 
    return [uiImage autorelease]; 
} 
1

Açıkça çalışma zamanı sırasında trafo kaydetmeniz gerekir.

Bunu yapmak için iyi bir yer, NSManagedObject varlık alt sınıfınızdaki Class initialize yöntemini geçersiz kılmaktır. Daha önce bahsedildiği gibi Çekirdek Veri hatası olarak bilinir. Apple'ın konum kod örnekten çok önemli kod aşağıdadır, bu test edilir ve çalışır: 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

Evet, bunu biliyorum ve yapıyorum. –

+0

Benim durumumda tam olarak sorun buydu. Ayrıca, transformatör adının veri modelinde bildirdiğinizle eşleşip eşleşmediğini ve eğer yöntemlerin tersini çevirmediyseniz, dönüştürülmüşValue ve reverseTransformedValue öğelerini de kontrol edebilirsiniz. – Lukasz

İlgili konular