继承NSMutableDictionary并使用NSKeyedArchiver序列化的自定义对象无法反序列化

Custom object inheriting NSMutableDictionary and serialized with NSKeyedArchiver can't be deserialized

Class 未正确取消存档。 请参阅下面的代码示例。

@interface A : NSMutableDictionary 
@end

@implementation A
- (void)encodeWithCoder:(NSCoder *)aCoder
{

}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {

    }   
    return self;
}
@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    A *a = [[A alloc] init];

    NSMutableDictionary *dict = [NSMutableDictionary new];
    dict[@"some"] = a;

    NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:dict];

    dict = [NSKeyedUnarchiver unarchiveObjectWithData:archive];

    NSLog(@"%@",dict);
}

调用 unarchiveObjectWithData 后,dict 包含对键 @"some" 但对象是 NSMutableDictionary 而不是 A class。并且在调用 unarchiveObjectWithData 时没有发生 initWithCoder 调用。 那么,如何让它代码工作呢?为什么class继承NSMutableDictionary没有被反序列化?

此方法:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
}

包含对象对自身进行编码的指令,即"don't do anything"。它应该说的是:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    // perform the inherited behavior or encoding myself
    [super encodeWithCoder:encoder];
}

再次编辑,这个测试 class subclasses 一个 NSMutableDictionary 以最简单的方式:通过隐藏一个可变字典实例在它的实现中提供原始方法 (PLUS encodeWithCoder)

#import "MyDict.h"

@interface MyDict ()
@property(strong) NSMutableDictionary *internalDictionary;
@end

@implementation MyDict

// changed to the default init for the "new" constructor
- (id)init {
    self = [super init];
    if (self) {
        _internalDictionary = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (NSUInteger)count {
    return [self.internalDictionary count];
}

- (id)objectForKey:(id)aKey {
    return [self.internalDictionary objectForKey:aKey];
}

- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    return [self.internalDictionary setObject:anObject forKey:aKey];
}

- (void)removeObjectForKey:(id)aKey {
    return [self.internalDictionary removeObjectForKey:aKey];
}

- (NSEnumerator *)keyEnumerator {
    return [self.internalDictionary keyEnumerator];
}

// added encoding of the internal representation
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [super encodeWithCoder:aCoder];
    [aCoder encodeObject:_internalDictionary forKey:@"internalDictionary"];
}

// added decoding of the internal representation
- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        _internalDictionary = [aDecoder decodeObjectForKey:@"internalDictionary"];
    }
    return self;
}

- (Class)classForCoder {
    return self.class;
}

@end

再次编辑,这次完全是您的测试:

MyDict *a = [MyDict new];
a[@"hi"] = @"there";

NSMutableDictionary *dict = [NSMutableDictionary new];
dict[@"some"] = a;
NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:dict];
dict = [NSKeyedUnarchiver unarchiveObjectWithData:archive];
NSLog(@"%@", dict);

日志...

{ some = { hi = there; }; }