Проблема с трансформируемыми атрибутами основных данных для изображений
Я застрял на том, что должно быть очень простым делом: иметь Core Data Entity для хранения / отображения (с помощью привязок) изображения, назначенного в качестве преобразуемого атрибута.
Я прочитал много похожих постов в стеке (например, см. Здесь и здесь), но все еще испытываю проблемы с ним, после того, как разработал пример кода и исследовал другие статьи (например, см. Здесь и здесь). Это связано с моим предыдущим вопросом, который я до сих пор не решил.
Я создал простое основанное на doc приложение Core Data, чтобы продемонстрировать проблему. Управляемый объект Core Data называется "TheEntity", а атрибут "theImageAtt". Сущность, как определено в Базовых данных, показана ниже (ImageValueTransformer является NSValueTransformer):
Я позволил XCode генерировать заголовок подкласса NSManagedObject и файлы реализации (я упустил код для атрибута "name", чтобы сделать его проще):
// TheEntity.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "ImageValueTransformer.h"
@interface TheEntity : NSManagedObject
@property (nonatomic, retain) NSImage * theImageAtt;
@end
-----------------------
// TheEntity.m
#import "TheEntity.h"
@implementation TheEntity
@dynamic theImageAtt;
@end
Ниже приведены заголовок и файлы реализации для моего "ImageValueTransformer". Множество примеров этого в стеке и в других местах (повторение tiff произвольно).
// ImageValueTransformer.h
#import <Foundation/Foundation.h>
@interface ImageValueTransformer : NSValueTransformer
@end
-------------------------------
// ImageValueTransformer.m
#import "ImageValueTransformer.h"
@implementation ImageValueTransformer
+ (BOOL)allowsReverseTransformation {return YES;}
+ (Class)transformedValueClass {
return [NSData class]; // have also tried: return [NSImage class];
}
- (id)transformedValue:(id)value {
NSData *data = [value TIFFRepresentation];
return data;
}
- (id)reverseTransformedValue:(id)value {
NSImage *imageRep = [[NSImage alloc] initWithData:value];
return imageRep;
}
@end
Value Transformer может быть инициализирован / зарегистрирован путем выделения его экземпляра в MyDocument.m, но, в конце концов, это не имеет большого значения, если заголовок преобразователя импортируется в заголовок объекта (см. Выше). Я экспериментировал с этим, и это не устраняет ошибку, которую я получаю ниже. Для справки, ранее обсуждалось, нужно ли регистрировать преобразователь значения (см. Комментарии CornPuff и Brian Webster).
Возвращаясь к рассматриваемой проблеме, здесь есть хороший пример кода от Apple, который показывает альтернативную инициализацию преобразователя значения, я тоже попробовал эту настройку.
Вводя это в действие, у меня есть метод, чтобы загрузить тестовое изображение и назначить его трансформируемому атрибуту в MyDocument.m (из выбранного экземпляра Entity в NSTable):
- (IBAction)addImg:(id)sender {
NSImage *theImg = [[NSImage alloc] initWithContentsOfFile:@"/Desktop/testImage.jpg"];
//[theImageView setImage:theImg]; // as a test, this displays ok
// "theEntities" below are defined as an IBOutlet to my Array Controller:
[theEntities setValue:theImg forKeyPath:@"selection.theImageAtt"];
NSLog(@"after setting the image ..."); // this never logs
}
Обнуление того места, где код нарушается, строка ниже:
[theEntities setValue:theImg forKeyPath:@"selection.theImageAtt"];
выдает ошибку:
Cannot create BOOL from object <4d4d002a 0003717e 8989898a 8a8a8b8b 8b8b8b8b
8a8a8a89 89898888 88878787 8a8a8a89 89898888 88888888 88888889 89898a8a
8a8a8a8a 8b8b8b88 88888787 87898989 8a8a8a89 89898a8a 8a8c8c8c 8b8b8b8a
8a8a8888 .... and so on for the size of the Image array ...
Если я закомментирую вышеупомянутую строку, то мой NSTable заполняется просто отлично (поэтому привязки и контроллер массива выглядят нормально), но, конечно, без изображения в NSImageView.
В качестве проверки код преобразования, используемый в преобразователе изображений, работает должным образом (это проверяется отдельно от преобразователя значения):
// Image to Data Conversion:
NSImage *imageIn = [[NSImage alloc] initWithContentsOfFile:@"testImage.jpg"];
NSData *imgData = [imageIn TIFFRepresentation];
NSImage *imageOut = [[NSImage alloc] initWithData:imgData];
[theImageDisplay setImage:imageOut];
Чего мне не хватает в этом?
1 ответ
Я обнаружил, что ошибка, указанная выше, а именно,
Cannot create BOOL from object ...
не возникает при использовании ячейки изображения или ячейки изображения (подклассы NSImageView), а не пользовательского представления, в которое я пытался записать ранее.
Так что сейчас я использую преобразователь значения по умолчанию, а не настраиваемый преобразователь значения. Это работоспособное решение, но с академической точки зрения было бы неплохо узнать, почему пользовательское представление по умолчанию приводило к ошибкам при привязке к атрибуту базовых данных (определяемому как преобразуемое в модели базовой даты).
Немного углубившись в это, Image Well наследуется от NSImageView, поэтому, по крайней мере, одно отличие состоит в том, что они различаются в отношении свойства "editable" (Image Wells являются редактируемыми, что хорошо работает с Drag-n-Drop). Поэтому, пытаясь согласовать эти два параметра, я настроил свой пользовательский вид на редактируемый, думая, что это может решить проблему:
theImageView = [[NSImageView alloc] init];
[theImageView setEditable:YES];
Но это должно быть что-то еще, это не устраняет ошибку выше. По крайней мере, сейчас у меня есть работоспособное решение. Если другие столкнутся с этим, я надеюсь, что эти заметки полезны!