使用 NSKeyedArchiver 将 [UIColor colorWithPatternImage:image] UIColor 保存到 Core Data

发布于 2024-12-04 20:36:05 字数 681 浏览 1 评论 0原文

我无法从使用工厂方法

[UIColor colorWithPatternImage:image]

创建的 UIColor (带有图案)创建 NSData 对象,对于标准 UIColor 对象效果很好。想知道是否有另一种方法可以将带有模式的 UIColor 保存到核心数据中。

我正在使用以下代码来存档 UIColor (带有模式)...

- (id)transformedValue:(id)value {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
return data;

}

这些是我收到的错误...

-[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'

I'm unable to create an NSData object from a UIColor (with a pattern) created with the factory method

[UIColor colorWithPatternImage:image]

works fine for standard UIColor objects. Wondering if there is another way to save a UIColor with a pattern into Core Data.

I am using the following code to archive the UIColor (with a pattern)...

- (id)transformedValue:(id)value {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
return data;

}

and these are the errors I'm receiving...

-[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'

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

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

发布评论

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

评论(3

又怨 2024-12-11 20:36:05

哦是的!我得到了它。在以下人员/帖子的帮助下...

给了我使用关联对象的想法

关联对象的说明

和方法调配

在 UIColor 上创建一个类别。使用关联对象在 UIColor 实例中设置对图案图像的引用(有点像动态属性),不要忘记导入 。创建 UIColor color = [UIColor colorWithPatternImage:selectedImage] 时,还要在颜色 [color setAssociatedObject:selectedImage] 上设置关联对象。

然后在类别中实现自定义的encodeWithCoder和initWithCoder方法来序列化UIImage。

最后在 main.m 文件中进行一些方法调整,以便您可以从 UIColor 类别中调用原始的 UIColorencodeWithCoder 和 initWithCoder 方法。那么你甚至不需要为核心数据编写自己的值转换器,因为 UIColor 实现了 NSCoding 协议。下面的代码...

UIColor+patternArchive

#import "UIColor+patternArchive.h"
#import <objc/runtime.h>

@implementation UIColor (UIColor_patternArchive)

static char STRING_KEY; // global 0 initialization is fine here, no 
                        // need to change it since the value of the
                        // variable is not used, just the address

- (UIImage*)associatedObject 
{ 
    return objc_getAssociatedObject(self,&STRING_KEY); 
} 

- (void)setAssociatedObject:(UIImage*)newObject 
{ 
    objc_setAssociatedObject(self,&STRING_KEY,newObject,OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
}

- (void)encodeWithCoderAssociatedObject:(NSCoder *)aCoder 
{ 
    if (CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor))==kCGColorSpaceModelPattern) 
    { 
        UIImage *i = [self associatedObject]; 
        NSData *imageData = UIImagePNGRepresentation(i);
        [aCoder encodeObject:imageData forKey:@"associatedObjectKey"]; 
        self = [UIColor clearColor]; 
    } else {

        // Call default implementation, Swizzled
        [self encodeWithCoderAssociatedObject:aCoder];
    }
}

- (id)initWithCoderAssociatedObject:(NSCoder *)aDecoder 
{ 
    if([aDecoder containsValueForKey:@"associatedObjectKey"])
    { 
        NSData *imageData = [aDecoder decodeObjectForKey:@"associatedObjectKey"];
        UIImage *i = [UIImage imageWithData:imageData];
        self = [[UIColor colorWithPatternImage:i] retain]; 
        [self setAssociatedObject:i]; 
        return self; 
    } 
    else 
    { 
        // Call default implementation, Swizzled
        return [self initWithCoderAssociatedObject:aDecoder];
    } 
}

main.m

#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "UIColor+patternArchive.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Swizzle UIColor encodeWithCoder:
    Method encodeWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], @selector(encodeWithCoderAssociatedObject:));
    Method encodeWithCoder = class_getInstanceMethod([UIColor class], @selector(encodeWithCoder:));
    method_exchangeImplementations(encodeWithCoder, encodeWithCoderAssociatedObject);

    // Swizzle UIColor initWithCoder:
    Method initWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], @selector(initWithCoderAssociatedObject:));
    Method initWithCoder = class_getInstanceMethod([UIColor class], @selector(initWithCoder:));
    method_exchangeImplementations(initWithCoder, initWithCoderAssociatedObject);

    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

Oh Yes! I got it. With a lot of help from the following people/posts...

Gave me the idea to use associatedObjects

Explanation of associatedObjects

and method swizzling

Create a category on UIColor. Use an Associated Object to set a reference to the pattern image in the UIColor instance (kind of like a dynamic property), don't forget to import <objc/runtime.h>. When you create your UIColor color = [UIColor colorWithPatternImage:selectedImage], also set the associated object on the color [color setAssociatedObject:selectedImage].

Then implement custom encodeWithCoder and initWithCoder methods in the category to serialize the UIImage.

And finally do some method swizzling in the main.m file so you can invoke the original UIColor encodeWithCoder and initWithCoder methods from within your UIColor Category. Then you don't even need to write your own Value Transformer for Core Data because UIColor implements the NSCoding protocol. Code below...

UIColor+patternArchive

#import "UIColor+patternArchive.h"
#import <objc/runtime.h>

@implementation UIColor (UIColor_patternArchive)

static char STRING_KEY; // global 0 initialization is fine here, no 
                        // need to change it since the value of the
                        // variable is not used, just the address

- (UIImage*)associatedObject 
{ 
    return objc_getAssociatedObject(self,&STRING_KEY); 
} 

- (void)setAssociatedObject:(UIImage*)newObject 
{ 
    objc_setAssociatedObject(self,&STRING_KEY,newObject,OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
}

- (void)encodeWithCoderAssociatedObject:(NSCoder *)aCoder 
{ 
    if (CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor))==kCGColorSpaceModelPattern) 
    { 
        UIImage *i = [self associatedObject]; 
        NSData *imageData = UIImagePNGRepresentation(i);
        [aCoder encodeObject:imageData forKey:@"associatedObjectKey"]; 
        self = [UIColor clearColor]; 
    } else {

        // Call default implementation, Swizzled
        [self encodeWithCoderAssociatedObject:aCoder];
    }
}

- (id)initWithCoderAssociatedObject:(NSCoder *)aDecoder 
{ 
    if([aDecoder containsValueForKey:@"associatedObjectKey"])
    { 
        NSData *imageData = [aDecoder decodeObjectForKey:@"associatedObjectKey"];
        UIImage *i = [UIImage imageWithData:imageData];
        self = [[UIColor colorWithPatternImage:i] retain]; 
        [self setAssociatedObject:i]; 
        return self; 
    } 
    else 
    { 
        // Call default implementation, Swizzled
        return [self initWithCoderAssociatedObject:aDecoder];
    } 
}

main.m

#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "UIColor+patternArchive.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Swizzle UIColor encodeWithCoder:
    Method encodeWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], @selector(encodeWithCoderAssociatedObject:));
    Method encodeWithCoder = class_getInstanceMethod([UIColor class], @selector(encodeWithCoder:));
    method_exchangeImplementations(encodeWithCoder, encodeWithCoderAssociatedObject);

    // Swizzle UIColor initWithCoder:
    Method initWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], @selector(initWithCoderAssociatedObject:));
    Method initWithCoder = class_getInstanceMethod([UIColor class], @selector(initWithCoder:));
    method_exchangeImplementations(initWithCoder, initWithCoderAssociatedObject);

    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}
你不是我要的菜∠ 2024-12-11 20:36:05

由于 UIColor 实现了 NSCoding 协议,因此您不必编写自己的转换器,而只需告诉 Core Data 使用 NSKeyedUnarchiveFromDataTransformerName 转换(这是默认设置)。

据我所知,该转换处理模式在 UIColor 对象中。

Since UIColor implements the NSCoding protocol, you don't have to write your own transformer but can just tell Core Data to use the NSKeyedUnarchiveFromDataTransformerName transform (which is the default.)

To my knowledge, that transform handles patterns in UIColor objects.

開玄 2024-12-11 20:36:05

我确信有一种方法可以将 uicolor 转换为十六进制字符串,您可以简单地将具有“NSString”的十六进制字符串存储在核心数据模型中。

如何将 RGB 十六进制字符串转换为Objective-c 中的 UIColor?

Im sure theres a way to convert uicolor into hex strings, you could simply store the hex string has "NSString" in core data model.

How can I convert RGB hex string into UIColor in objective-c?

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