Использование NSValueTransformer для установки значений экземпляра NSManagedObject

Я использую пользовательский NSValueTransformer для хранения информации о цвете в моем хранилище базовых данных. Преобразование между преобразуемыми данными и экземпляром UIColor прекрасно работает, когда данные о цветах уже находятся в хранилище (т. Е. После того, как приложение было запущено и завершилось один раз). Однако, когда я впервые запускаю приложение и загружаю эти значения (из текстового файла), они "застряли" как NSCFStrings.

В этой строке кода "атрибуты" словарь имеет ключи, которые являются именами атрибутов NSManagedObject и значениями, которые являются ожидаемыми значениями для этих атрибутов. В моем примере цвета пара ключ-значение "color":"1,1,1,0.5"

[object setValue:[attributes valueForKey:attribute] forKey:attribute];

Значение для "color" теперь будет оставаться строкой в ​​этом случае, пока оно не будет преобразовано через мой NSValueTransformer, а затем преобразовано в UIColor при повторном запуске приложения.

Я мог бы просто сделать то же самое преобразование здесь, что я делаю в NSValueTransformer, но это в служебном классе, который я написал, который теоретически может быть использован для любого преобразователя. Я также подумал о том, чтобы найти способ вытащить из памяти все вновь созданные экземпляры NSManagedObject, тем самым вынудив преобразование пройти, но это выглядит как хак.

Примечание: этот "взлом" работает для меня, и давайте продолжим, но все еще чувствую себя ужасно. Используйте метод сброса NSManagedObjectContext, если у вас есть похожие проблемы / вы ищете решение "просто работа".

Есть идеи?

(У меня есть догадка, это похоже на " Почему мой трансформируемый атрибут Core Data не использует мой собственный NSValueTransformer? ", Но вне заголовка наши проблемы кажутся другими)

Вот мой NSValueTransformer

@implementation UIColorRGBValueTransformer

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

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    return [value dataUsingEncoding:NSUTF8StringEncoding];
}

- (id)reverseTransformedValue:(id)value
{
    NSString *colorAsString = [[[NSString alloc] initWithData:value encoding:NSUTF8StringEncoding] autorelease];
    NSArray *components = [colorAsString componentsSeparatedByString:@","];
    CGFloat r = [[components objectAtIndex:0] floatValue];
    CGFloat g = [[components objectAtIndex:1] floatValue];
    CGFloat b = [[components objectAtIndex:2] floatValue];
    CGFloat a = [[components objectAtIndex:3] floatValue];
    return [UIColor colorWithRed:r green:g blue:b alpha:a];

    return nil;
}

@end

1 ответ

Решение

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

Обычно вам нужно написать собственный преобразователь значения для определенного классом системы, когда вы хотите сделать что-то нестандартное. В подавляющем большинстве случаев предпочтительным методом является использование по умолчанию NSKeyedUnarchiveFromDataTransformerName. Любой класс, который реализует протокол NSCoding, может использовать этот преобразователь значения.

Так как UIColor действительно реализует протокол NSCoding, вы можете просто установить атрибут "преобразуемый" и NSKeyedUnarchiveFromDataTransformerName автоматически заполнит имя преобразователя (по крайней мере, в Xcode 3.x.). При использовании Core Data создаст соответствующие средства доступа, так что вы можете установить и получить атрибут UIColor, как и любой другой ключ:

[aMoObject setValue:aUIcolorObj forKey:@"colorAttributeName"];

Как хорошее практическое правило, API сделает большую часть работы за вас в случае классов API. Если вы усердно работаете с системным классом, возможно, вы что-то упустили.

Другие вопросы по тегам