UIImage和NSCoding iOS 5.1

ody*_*yth 5 objective-c ios

在iOS 5.1之前,如果你想在UIImage中使用NSCoding协议,你必须做这样的事情.

@interface UIImage (NSCoding)

-(id)initWithCoder:(NSCoder *)deocder;
-(void)encodeWithCoder:(NSCoder *)encoder;

@end
Run Code Online (Sandbox Code Playgroud)

然后自己实现它.但是,对于iOS 5.1,这会在此协议的.M文件中生成警告"类正在实现一个也将由其主类实现的方法".现在如果我删除这个扩展类iOS5.1会很高兴,但是这应该在iOS4.0上崩溃和刻录.那么最好的行动方案是什么?

sze*_*ian 7

我有同样的问题,因为使用子类而不是cateogry为时已晚,我遵循zoul的建议使用class_addMethod,下面是我的实现:

#import "UIImage-NSCoding.h"
#include <objc/runtime.h>
#define kEncodingKey        @"UIImage"

static void __attribute__((constructor)) initialize() {
    @autoreleasepool {

        if (![[UIImage class] conformsToProtocol:@protocol(NSCoding)]) {
            Class class = [UIImage class];

            if (!class_addMethod(
                                 class,
                                 @selector(initWithCoder:), 
                                 class_getMethodImplementation(class, @selector(initWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(initWithCoder:), YES, YES).types
                                )) {
                                    NSLog(@"Critical Error - [UIImage initWithCoder:] not defined.");
                                }

            if (!class_addMethod(
                                 class,
                                 @selector(encodeWithCoder:),
                                 class_getMethodImplementation(class, @selector(encodeWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(encodeWithCoder:), YES, YES).types
                                )) {
                                    NSLog(@"Critical Error - [UIImage encodeWithCoder:] not defined.");
                                }

        } 
    }
}

@implementation UIImage(NSCoding)

- (id) initWithCoderForArchiver:(NSCoder *)decoder {

    if ((self = [super init]))
    {
        NSData *data = [decoder decodeObjectForKey:kEncodingKey];
        self = [self initWithData:data];
    }

    return self;

}

- (void) encodeWithCoderForArchiver:(NSCoder *)encoder {

    NSData *data = UIImagePNGRepresentation(self);
    [encoder encodeObject:data forKey:kEncodingKey];

}

@end
Run Code Online (Sandbox Code Playgroud)

到目前为止,我没有发现任何进一步的问题.希望能帮助到你!

[注意]

如果您使用此UIImage类别来存档UIImageViewer对象,请注意iOS 5中的UIImageViewer的 NSCoding实现似乎已被破坏.保存和加载后,当在XIB中指定时,UIImageViewer的图像属性会丢失(我还没有尝试在代码中创建UIImageViewer对象时是否存在相同的问题).这已在iOS 6中修复.

[更新]

我更改了我的代码以在+ load中添加方法而不是初始化(),它仍然只执行一次,但更早.我目前的实施:

#import "UIImage+NSCoding.h"
#import <objc/runtime.h>
#define kEncodingKey        @"UIImage"

@implementation UIImage (NSCoding)

+ (void) load
{

    @autoreleasepool {
        if (![UIImage conformsToProtocol:@protocol(NSCoding)]) {
            Class class = [UIImage class];
            if (!class_addMethod(
                                 class,
                                 @selector(initWithCoder:), 
                                 class_getMethodImplementation(class, @selector(initWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(initWithCoder:), YES, YES).types
                                 )) {
                NSLog(@"Critical Error - [UIImage initWithCoder:] not defined.");
            }

            if (!class_addMethod(
                                 class,
                                 @selector(encodeWithCoder:),
                                 class_getMethodImplementation(class, @selector(encodeWithCoderForArchiver:)),
                                 protocol_getMethodDescription(@protocol(NSCoding), @selector(encodeWithCoder:), YES, YES).types
                                 )) {
                NSLog(@"Critical Error - [UIImage encodeWithCoder:] not defined.");
            }

        } 
    }
}

- (id) initWithCoderForArchiver:(NSCoder *)decoder {
    if (self = [super init]) {
        NSData *data = [decoder decodeObjectForKey:kEncodingKey];
        self = [self initWithData:data];
    }

    return self;

}

- (void) encodeWithCoderForArchiver:(NSCoder *)encoder {

    NSData *data = UIImagePNGRepresentation(self);
    [encoder encodeObject:data forKey:kEncodingKey];

}

@end
Run Code Online (Sandbox Code Playgroud)