2012-03-08 59 views
5

在iOS 5.1之前,如果你想在UIImage中使用NSCoding協議,你必須這樣做。UIImage和NSCoding iOS 5.1

@interface UIImage (NSCoding) 

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

@end 

然後自己實施。但是,對於iOS 5.1,此協議的.M文件中會生成警告「類別正在實施一種方法,該方法也將由其主類實現」。現在,如果我刪除這個擴展類iOS5.1會很高興,但是這會在iOS4.0上崩潰和燒燬。那麼最好的行動是什麼?

+0

這個問題已經被問及當時這是我是誰的答案是 - 我不記得是怎樣的問題,因爲它是早在夏天,但我記得有一個重複這個問題在這裏。 – 2012-10-06 08:44:19

+0

啊,這是它:http://stackoverflow.com/questions/11950173/conditional-categories-in-mountain-lion/11950348#11950348 – 2012-10-06 08:50:10

回答

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 

到目前爲止,我還沒有發現任何進一步的問題 希望它有幫助!

[注意]

如果爲了存檔UIImageViewer對象使用UIImage的類別,提防在iOS 5中NSCoding實施UIImageViewer似乎被打破。 UIImageViewer的image屬性在保存和加載後會丟失,當它在XIB中指定時(我沒有試圖查看在代碼中創建UIImageViewer對象時是否存在相同的問題)。這已被固定在IOS 6.

[UPDATES]

我改變代碼添加在+負載方法,而不是初始化(),仍在只執行一次,但是早。我目前的執行情況:

#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 
+0

你介意提供一些關於這段代碼去哪裏的上下文嗎?我有一個包含2個NSString和一個UIImage的自定義對象類,它會在那裏? – 2012-06-20 10:34:51

+0

以上代碼是作爲UIImage的類別實現的。基本上我所做的只是擴展了Jeff LaMarche實施的功能(http://iphonedevelopment.blogspot.it/2009/03/uiimage-and-nscoding.html),以避免在iOS 5.1中出現警告消息。 – szemian 2012-06-20 10:47:07

+0

啊我看到了,謝謝:) – 2012-06-20 10:55:08

0

一種方法是動態修補UIImage類,以便在iOS 4上運行時(或更好,當方法丟失時)添加所需的方法。 Here’s a sample project on GitHub做了類似的事情,它增加了對iOS 4的控制器遏制支持(關鍵是class_addMethod函數)。但是這對於生產代碼來說太過神奇了,所以如果有更簡單的答案,那就去吧。

+0

爲什麼這對生產代碼來說太神奇了? – odyth 2012-03-19 22:36:19

+0

使用運行時的類進行搗亂是很脆弱的,很難預見可能出現的問題。 – zoul 2012-03-20 07:10:54

2

而不是在UIImage上使用一個類別,它不是更清潔的子類嗎?

然後,您可以實現initWithCoderencodeWithCoder並在5.1之前和5.1之前使用UIImage的NSCoding實現。

+1

只有一個地方我需要保存UIImage,子類化將要求我總是使用我發明的這個新的Image類。 – odyth 2012-03-19 22:45:49

+0

+1:作文>子類(在我看來) – nielsbot 2012-10-06 09:04:53