iOS:如何序列化非NSCoding兼容对象

时间:2012-09-18 09:40:56

标签: ios serialization nscoding

我已经四处看看并在此处找到了结束答案:

  

Correct way to save/serialize custom objects in iOS

但这仅适用于用户创建的自定义对象。我的问题是序列化“SKProduct”,它是一个非NSCoding兼容的派生类。具体来说,我遇到的确切错误:

-[SKProduct encodeWithCoder:]: unrecognized selector sent to instance 0x4027160

有没有人有类似的经历?

1 个答案:

答案 0 :(得分:2)

我会在这个答案前面说这可能是一种更简单的方法;但归档和取消归档期间的类替换是您可以采取的一种方法。

在归档期间,您可以选择设置符合NSKeyedArchiverDelegate协议的委托。所有方法都是可选的。代理在编码期间收到消息archiver:willEncodeObject:消息。如果您希望在归档期间替换类,则可以创建替换对象并将其返回。否则只返回原始对象。

在您的情况下,您可以为SKProduct创建一个“影子对象”,它封装了您感兴趣的序列化原始类的所有属性。然后在归档期间替换该类。在取消归档期间,您可以撤消该过程并返回SKProduct

为了便于说明,这是一个例子。请注意,我已经省略了反向替换部分 - 但如果您阅读NSKeyedUnarchiverDelegate上的文档,我认为这很清楚。

#import <Foundation/Foundation.h>

@interface NoncompliantClass:NSObject
@property (nonatomic,assign) NSInteger foo;
@end

@implementation NoncompliantClass
@synthesize foo = _foo;
@end

@interface CompliantClass:NSObject <NSCoding>
@property (nonatomic,assign) NSInteger foo;
@end

@implementation CompliantClass
@synthesize foo = _foo;

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeInteger:self.foo forKey:@"FooKey"];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if( !self ) { return nil; }

    _foo = [coder decodeIntegerForKey:@"FooKey"];
    return self;
}

@end

@interface ArchiverDelegate:NSObject <NSKeyedArchiverDelegate>
@end

@implementation ArchiverDelegate
- (id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object {
    NSString *objClassName = NSStringFromClass([object class]);
    NSLog(@"Encoding %@",objClassName);
    if( [object isMemberOfClass:[NoncompliantClass class]] ) {
        NSLog(@"Substituting");
        CompliantClass *replacementObj = [CompliantClass new];
        replacementObj.foo = [object foo];
        return replacementObj;
    }
    return object;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NoncompliantClass *cat1 = [NoncompliantClass new];
        NoncompliantClass *cat2 = [NoncompliantClass new];
        NSArray *herdableCats = [NSArray arrayWithObjects:cat1,cat2,nil];

        ArchiverDelegate *delegate = [ArchiverDelegate new];
        NSMutableData *data = [NSMutableData data];
        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
        [archiver setDelegate:delegate];
        [archiver encodeObject:herdableCats forKey:@"badKitties"];
        [archiver finishEncoding];
    }
}

此日志:

2012-09-18 05:24:02.091 TestSerialization[10808:303] Encoding __NSArrayI
2012-09-18 05:24:02.093 TestSerialization[10808:303] Encoding NoncompliantClass
2012-09-18 05:24:02.093 TestSerialization[10808:303] Substituting
2012-09-18 05:24:02.094 TestSerialization[10808:303] Encoding NoncompliantClass
2012-09-18 05:24:02.094 TestSerialization[10808:303] Substituting