Базовые данные, привязки, преобразователи значений: сбой при сохранении - PullRequest
2 голосов
/ 22 мая 2010

Я пытаюсь сохранить изображение PNG в основном хранилище данных, поддерживаемом базой данных sqlite.Так как я собираюсь использовать эту базу данных на iPhone, я не могу хранить NSImage объекты напрямую.Я хотел использовать привязки и подкласс NSValueTransformer для обработки транскодирования из NSImage (полученного с помощью скважины Image в моем GUI) в NSData, содержащее двоичное представление PNG изображения.Я написал следующий код для 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.В Интерфейсном Разработчике столбец таблицы и лунка изображения оба привязаны к этому свойству и оба имеют правильное имя преобразователя значения (изображение, уроненное в лунку изображения, отображается в столбце таблицы).Преобразователь регистрируется и вызывается при каждом добавлении изображения или перезагрузке строки (проверяется с помощью вызовов NSLog()).Проблема возникает, когда я пытаюсь сохранить управляемые объекты.Вывод консоли показывает сообщение об ошибке:

[длина NSImage]: нераспознанный селектор отправлен в экземпляр 0x1004933a0

Похоже, что данные ядра используют преобразователь значения для полученияNSImage возвращается из NSData и затем пытается сохранить NSImage вместо NSData.

Возможно, есть обходные пути, такие как тот, который представлен в в этом посте , ноМне бы очень хотелось понять, почему мой подход ошибочен.

Заранее спасибо за ваши идеи и объяснения.

Ответы [ 2 ]

1 голос
/ 22 мая 2010

Я в итоге заставил его работать (лучше спать на нем). Были две проблемы. Первым было то, что я указал один и тот же преобразователь значения как в привязках IB, так и в базовой модели данных, и он был избыточным.

Насколько я понимаю, привязки IB для указанных преобразователей значений фактически преобразуют значения между представлениями и контроллерами, тогда как преобразователь значений данных ядра действует как посредник между управляемыми объектами и постоянным хранилищем.

Что еще хуже, вторая проблема заключалась в том, что мой стоимостной преобразователь был перевернут. Сообщение transformValue отправляется при сохранении объектов (управляемый объект -> хранилище), а сообщение reverseTransformedValue отправляется при загрузке значений из хранилища, что несколько противоположно направлению преобразователей, используемых при привязке объектов вида к объектам модели. , Я получил подсказку из руководства по программированию основных данных , где вы можете прочитать следующую загадочную заметку:

Важное замечание: Хотя преобразователь по умолчанию является преобразователем, указанным NSKeyedUnarchiveFromDataTransformerName, этот преобразователь фактически используется в обратном порядке. Если вы укажете преобразователь по умолчанию явно, Core Data будет использовать его «в неправильном направлении».

Несмотря на то, что моя программа работает до сих пор, я хотел бы получить подтверждение от кого-то с опытом работы с основными данными, и я был бы признателен, если бы вы указали мне некоторые документы по этому вопросу, которые я мог бы пропустить.

Заранее спасибо.

Рабочий код:


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

1 голос
/ 22 мая 2010

В transformValue: вы идете прямо от NSData к NSImage, но в reverseTransformedValue: вы переходите от NSImage к NSBitmapImageRep к NSData.Таким образом, эти два не работают вместе, потому что они используют разные методологии.Данные в вашей модели на самом деле являются данными NSBitmapImageRep, а не данными NSImage.Они должны быть точными противоположностями друг другу.

Кстати, недавно я опубликовал трансформер для этого в другом посте.Вы можете видеть это здесь .И, конечно же, вам вообще не нужен специальный преобразователь, поскольку вы можете просто использовать NSKeyedArchiver.NSImage придерживается протокола NSCoder, поэтому он будет обрабатывать преобразование для вас.

...