使用密钥归档/取消归档父子对象

Posted

技术标签:

【中文标题】使用密钥归档/取消归档父子对象【英文标题】:Archive/Unarchive Parent-Child objects with a key 【发布时间】:2017-03-17 05:16:18 【问题描述】:

我有一个类A 和一个子类B

@interface A:NSObject<NSCoding>
String a;
String b;
@end
@interface B: A<NSCoding>
int c;
// `a` and `b` attributes are inherited
@end;

我想使用属性aA 的一些对象和B 的一些对象归档为key。 两个类中的encodingdecoding 协议都被定义为:

@implementation A
...
- (void) encodeWithCoder:(NSCoder *)encoder 
    //[super encodeWithCoder:encoder];
    [encoder encodeObject:self forKey:a];


- (id)initWithCoder:(NSCoder *)decoder 
    // self = [super initWithCoder:decoder];
    if (self=[super init]) 
        self = [decoder decodeObjectForKey:a];
    
    return self;

@end

@implementation B
..
 - (void) encodeWithCoder:(NSCoder *)encoder 
    [super encodeWithCoder:encoder];
    [encoder encodeObject:self forKey:super.a];


- (id)initWithCoder:(NSCoder *)decoder 
    //self = [super initWithCoder:decoder];
    if (self) 
        self = [decoder decodeObjectForKey:super.a];
    
    return self;

对于一些对象列表dataArray = [A("One"), B("Two")],归档逻辑是

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
            NSError* error = nil;
            BOOL success = [data writeToFile: @"xyz.dat" options:0 error: &error];
            if (!success)
                NSLog( @"error = %@", [error description] );

再次从存档数据中读取:

NSData *lD = [[NSData alloc] initWithContentsOfFile:@"xyz.dat"];
NSKeyedUnarchiver *arc = [[NSKeyedUnarchiver alloc] initForReadingWithData:lD];

现在将属性为a 的对象设置为"One" 在尝试从存档数据中读取对象时,我收到了null

 NSLog(@"Value - %@",[arc decodeObjectForKey:@"One"]);

【问题讨论】:

查看此链接***.com/questions/41116832/… 【参考方案1】:

也许,问题在于编码self。 我做了以下更改:

@implementation A
...
- (void) encodeWithCoder:(NSCoder *)encoder 
    if(self.a!=nil)
        [encoder encodeObject:self.a forKey:@"a"];
    if(self.b!=nil)
        [encoder encodeObject:self.b forKey:@"b"];


- (id)initWithCoder:(NSCoder *)decoder 
    self=[super init];
    if (self!=nil) 
        self.a= [decoder decodeObjectForKey:@"a"];
        self.b= [decoder decodeObjectForKey:@"b"]; 
    
    return self;

@end

@implementation B
..
 - (void) encodeWithCoder:(NSCoder *)encoder 
     [super encodeWithCoder:encoder ];
     [encoder encodeObject:self.c forKey:@"c"];


- (id)initWithCoder:(NSCoder *)decoder 
    if ( (self = [super initWithCoder:decoder ]) )
    
        self.c= [decoder decodeObjectForKey:@"c"];
    
    return self;

编码数据时:

NSMutableDictionary *dict = [NSMutableDictionary new]; 
[dict setObject:[[A alloc]init()] forKey:@"One"];//say
[dict setObject:[[B alloc]init()] forKey:@"Two"];//say

NSMutableData *yourData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:yourData];
for (NSString* key in dict) 
    id value = [dict objectForKey:key];
    [archiver encodeObject:value forKey: key];

[ archiver finishEncoding];
[yourData writeToFile:@"xyz.dat" atomically:YES];
[yourData release];
[archiver release]; 

及解码:

NSData *data = [[NSData alloc] initWithContentsOfFile:@"xyz.dat"];
NSKeyedUnarchiver *keyArc= [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSLog(@"%@",[keyArc decodeObjectForKey:@"One"]);
NSLog(@"%@",[keyArc decodeObjectForKey:@"Two"]);
[keyArc finishDecoding];

参考:https://***.com/a/10929284/2301570

【讨论】:

以上是关于使用密钥归档/取消归档父子对象的主要内容,如果未能解决你的问题,请参考以下文章

NSKeyedUnarchiver.unarchiveObject() 取消归档旧对象

如何在 Swift 中归档和取消归档自定义对象?或者如何在 Swift 中将自定义对象保存到 NSUserDefaults?

添加了一个自定义框架,现在 Swift 无法取消归档数据

在 Swift 中的 DocumentDirectory 中归档和取消归档数组

从 iCloud 文件中取消归档对象时出错

故事板错误取消归档文档对象 - *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil