【问题标题】:Saving [UIColor colorWithPatternImage:image] UIColor to Core Data using NSKeyedArchiver使用 NSKeyedArchiver 将 [UIColor colorWithPatternImage:image] UIColor 保存到核心数据
【发布时间】:2011-09-17 18:11:04
【问题描述】:

我无法从使用工厂方法创建的 UIColor(带有模式)创建 NSData 对象

[UIColor colorWithPatternImage:image]

适用于标准 UIColor 对象。想知道是否有另一种方法可以将带有模式的 UIColor 保存到 Core Data 中。

我正在使用以下代码来归档 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.'

【问题讨论】:

    标签: core-data nsdata uicolor nskeyedarchiver


    【解决方案1】:

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

    Gave me the idea to use associatedObjects

    Explanation of associatedObjects

    and method swizzling

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

    然后实现类中自定义的encodeWithCoder和initWithCoder方法,对UIImage进行序列化。

    最后在 main.m 文件中进行一些方法调配,以便您可以从 UIColor 类别中调用原始的 UIColor encodeWithCoder 和 initWithCoder 方法。然后你甚至不需要为 Core Data 编写你自己的 Value Transformer,因为 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;
    }

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 仍然不工作,有趣的是,当你不指定一个时,Core Data 将使用默认值转换器。它适用于标准 UIColor 对象,但对于具有模式的 UIColor 对象仍然会出现相同的错误。
      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2010-11-19
        • 2018-02-10
        • 2016-03-25
        • 2019-03-30
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        • 2010-11-09
        相关资源
        最近更新 更多