2

我已经环顾四周,在这里找到了关闭的答案:

在 iOS 中保存/序列化自定义对象的正确方法

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

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

有没有人有类似的经历?

4

1 回答 1

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
于 2012-09-18T10:32:18.357 回答