使用 NSValueTransformer 设置 NSManagedObject 实例的值

发布于 2024-11-14 15:30:42 字数 1608 浏览 3 评论 0原文

我正在使用自定义 NSValueTransformer 将颜色信息存储在我的核心数据存储中。一旦颜色数据已经存储在存储中(即一旦应用程序已经运行并退出一次),Transformable 数据和 UIColor 实例之间的转换就可以很好地工作。然而,当我第一次运行应用程序并加载这些值(从文本文件)时,它们“卡住”为 NSCFStrings。

在这行代码中,“属性”是一个字典,其键是 NSManagedObject 属性名称,值是这些属性的预期值。在我的颜色示例中,键值对是“color”:“1,1,1,0.5”

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

“color”的值现在在此实例中将保留为字符串,直到它通过我的 NSValueTransformer 进行转换,然后在以下情况下重新转换为 UIColor:应用程序再次运行。

我可以在这里进行与 NSValueTransformer 中相同的转换,但这是在我编写的实用程序类中,理论上可以用于任何变压器。我还想过找到一种方法将所有新创建的 NSManagedObject 实例从内存中取出,从而强制进行转换,但这看起来像是一种黑客攻击。

注意:这个“黑客”对我有用,让我继续,但仍然感觉很难看。如果您遇到类似问题/正在寻找“正常工作”的解决方案,请使用 NSManagedObjectContext 的重置方法。

有什么想法吗?

(我有预感这类似于“

这是我的 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

I am using a custom NSValueTransformer to store color information in my Core Data store. The transformation between Transformable data and a UIColor instance works great once the color data is in the store already (ie once the app has been run and quit once already). However when I first run the app and am loading in these values (from a text file) they "stuck" as NSCFStrings.

In this line of code "attributes" is a dictionary has keys which are NSManagedObject attribute names and values that are the expected values for those attributes. In my color example the key value pair is "color":"1,1,1,0.5"

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

The value for "color" will now remain a string in this instance until it's get transformed via my NSValueTransformer and then retransformed into a UIColor when the app gets run again.

I could just do the same transform here that I'm doing in the NSValueTransformer, but this is in a utility class I wrote that could theoretically be used for any transformer. I also thought of finding a way to get all newly created NSManagedObject instances out fo memory thereby forcing the transformation to go through, but that just seems like a hack.

Note: This "hack" works for me and let's me continue, but still feels ugly. Use NSManagedObjectContext's reset method if you're having similar problems / looking for a "just work" solution.

Any ideas?

(I have a hunch this is similar to " Why is my transformable Core Data attribute not using my custom NSValueTransformer? " but outside of the title our problems seem to be different)

Here is my 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

因为看清所以看轻 2024-11-21 15:30:42

您确实没有按预期使用可转换属性。你的方法理论上应该有效,但它是一个丑陋的拼凑。

当您想做一些非标准的事情时,通常只需为系统定义的类编写自定义值转换器。在绝大多数情况下,首选方法是使用默认的 NSKeyedUnarchiveFromDataTransformerName。任何实现 NSCoding 协议的类都可以使用该值转换器。

由于 UIColor 确实实现了 NSCoding 协议,因此您只需将属性设置为“transformable”,NSKeyedUnarchiveFromDataTransformerName 将自动填充变压器名称(至少在 Xcode 3.x 中是这样)。在使用中,Core数据将创建适当的访问器,以便您可以像任何其他键一样设置和获取 UIColor 属性:

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

作为一个好的经验法则,在 API 类的情况下,API 将为您完成大部分工作。如果您发现自己正在努力学习系统类,那么您可能错过了一些东西。

You're really not using the transformable attribute as intended. Your method should work in theory but it is an ugly kludge.

You usually only have to write a custom value transformer for a system defined class when you want to do something non-standard. In the vast majority cases, the preferred method is to use the default NSKeyedUnarchiveFromDataTransformerName. Any class that implements the NSCoding protocol can use that value transformer.

Since UIColor does implement the NSCoding protocol, you can just set the attribute to 'transformable' and the NSKeyedUnarchiveFromDataTransformerName will populate the transformer name automatically (at least it did in Xcode 3.x.) In use, Core Data will create the appropriate accessors so you can set and get the UIColor attribute just like any other key:

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

As a good rule of thumb, the API will do most of the work for you in the case of API classes. If you find yourself working hard with a system class, you've probably missed something.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文