objective-c - UIImage 和 NSCoding iOS 5.1

标签 objective-c ios

在 iOS 5.1 之前,如果你想将 NSCoding 协议(protocol)与 UIImage 一起使用,你必须这样做。

@interface UIImage (NSCoding)

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

@end

然后自己实现。然而,对于 iOS 5.1,这会在该协议(protocol)的 .M 文件中生成警告“Category is implementing a method which will also be implemented by its primary class”。现在,如果我删除这个扩展类,iOS5.1 会很高兴,但是这应该会在 iOS4.0 上崩溃并烧毁。那么最好的行动方案是什么?

最佳答案

我有同样的问题,因为现在使用子类而不是类别为时已晚,我听从了 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

到目前为止,我还没有发现任何进一步的问题。希望对您有所帮助!

[注意]

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

[更新]

我更改了我的代码以在 +load 中添加方法而不是 initialize(),它仍然只执行一次,但更早。我当前的实现:

#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

关于objective-c - UIImage 和 NSCoding iOS 5.1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9614171/

相关文章:

ios - Parse-Server iOS SDK - 创建返回 PFQuery 结果的函数

iphone - 向应用商店提交申请?

ios - 如何让替换 View 淡入旧 View 而不是与它交叉淡入淡出?

ios - 全局将 UIImageView 添加到 UINavigationBar 而不是标题

ios - 如何取消 iOS 中的完成处理程序

ios - UIPickerView 作为 UITextField 的输入 View

iphone - 为什么我尝试在背景上显示图像会导致显示白色?

ios - 处理日光时差

ios - 内存问题 - 生存与整体 -> 应用程序被杀死

ios - SDWebImage 下载后不显示(仅在重新打开 VController 后)