You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSKeyedUnarchiver解码始终返回nil的问题求助

问题诊断与修复方案

你的问题核心出在编码和解码的方法不匹配,NSKeyedArchiver是基于键值对的归档方案,而你当前的代码没有正确使用键相关的API,或者可以更简单地用便捷方法来处理整个根对象的归档。

一、编码环节的问题

你手动初始化了NSKeyedArchiver,但调用的encodeObject:是NSCoder的基础方法,在键式归档场景下这种写法没有把数组正确作为根对象归档,导致解码时无法识别。推荐用更简洁的便捷方法完成归档:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *fullFileName = [documentsDirectory stringByAppendingPathComponent:@"sessionDataSaveFile"];

NSError *archiveError = nil;
NSData *pData = [NSKeyedArchiver archivedDataWithRootObject:self.sessionData
                                     requiringSecureCoding:NO
                                                     error:&archiveError];
if (pData && !archiveError) {
    [pData writeToFile:fullFileName atomically:YES];
} else {
    NSLog(@"归档失败:%@", archiveError.localizedDescription);
}

这个方法会自动把你的NSMutableArray作为根对象完成归档,省去手动初始化archiver、拼接数据的步骤,避免手动操作可能带来的错误。

二、解码环节的问题

你用decodeObject:获取数据,但这个方法在NSKeyedUnarchiver中需要对应编码时的键,而你编码时未指定键,自然取不到数据。同样用便捷方法解码根对象:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *fullFileName = [documentsDirectory stringByAppendingPathComponent:@"sessionDataSaveFile"];

NSData *pData = [NSData dataWithContentsOfFile:fullFileName];
if (pData) {
    NSError *unarchiveError = nil;
    self.sessionData = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:pData
                                                         requiringSecureCoding:NO
                                                                         error:&unarchiveError];
    if (!self.sessionData && unarchiveError) {
        NSLog(@"解档失败:%@", unarchiveError.localizedDescription);
    }
}

这个方法会直接取出归档的根对象(也就是你的NSMutableArray),同时能捕获解码时的错误,方便你进一步排查问题。

三、额外检查点

即使修正了归档代码,也要确保自定义对象正确实现NSCoding协议:

  • 必须实现- (void)encodeWithCoder:(NSCoder *)coder和- (instancetype)initWithCoder:(NSCoder *)coder方法
  • 编码和解码时的键要完全对应,比如编码用[coder encodeObject:self.name forKey:@"name"],解码就要用_name = [coder decodeObjectForKey:@"name"]
  • 如果App部署目标是iOS 12+,即使禁用了secure coding,建议在自定义类中实现+ (BOOL)supportsSecureCoding并返回YES

为什么原始代码会失败?

你手动初始化NSKeyedArchiver后调用encodeObject:,相当于向归档中添加了一个无键对象,但NSKeyedUnarchiver默认基于键查找数据,所以decodeObject:无法找到对应内容。另外你手动把archiver的encodedData追加到另一个NSMutableData的步骤完全多余,encodedData本身就是完整的归档数据。

内容的提问来源于stack exchange,提问作者DaveMoore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:12:41