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

Swift 4中NSMutableArray解归档异常:归档多对象但解档仅返回1个

排查NSMutableArray归档后解归档元素始终为1的问题

嘿,我来帮你拆解这个问题!这种情况我之前也遇到过,大概率是你在存储/解归档的流程里没正确复用已有的数组,导致每次都覆盖了之前的数据,最后看起来只保留了一个元素。咱们一步步来分析:

最可能的原因:每次存储时都新建数组,覆盖旧数据

很多人会犯这个错误——每次添加对象时,直接创建一个新的NSMutableArray,加完对象就归档存储,完全忽略了UserDefaults里已经存过的旧数组。比如错误代码是这样的:

// ❌ 错误写法:每次都新建数组,覆盖之前的所有数据
NSMutableArray *tempArray = [NSMutableArray array];
[tempArray addObject:yourTargetObject];
NSData *archiveData = [NSKeyedArchiver archivedDataWithRootObject:tempArray requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:archiveData forKey:@"YourSavedArrayKey"];

这种写法每次都会把旧数组彻底覆盖,自然最后解归档出来永远只有一个元素。

正确的处理流程:先读旧数组,再追加,最后重新归档

你需要先从UserDefaults里取出已归档的数组(如果有的话),在这个数组基础上追加新对象,然后再重新归档存储。代码示例:

// ✅ 正确写法:复用已有数组,追加后再存储
NSString *const kSavedArrayKey = @"YourSavedArrayKey";

// 1. 取出已归档的旧数据
NSData *existingArchiveData = [[NSUserDefaults standardUserDefaults] objectForKey:kSavedArrayKey];
NSMutableArray *savedArray = nil;

// 2. 解归档得到数组,没有的话就新建
if (existingArchiveData) {
    // 注意:如果解归档出来的是不可变NSArray,要转成可变的
    NSArray *tempArray = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:existingArchiveData error:nil];
    savedArray = [NSMutableArray arrayWithArray:tempArray];
} else {
    savedArray = [NSMutableArray array];
}

// 3. 追加新对象
[savedArray addObject:yourTargetObject];
NSLog(@"当前数组元素数量:%lu", (unsigned long)savedArray.count); // 这里可以确认元素已加入

// 4. 重新归档并存储
NSData *newArchiveData = [NSKeyedArchiver archivedDataWithRootObject:savedArray requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:newArchiveData forKey:kSavedArrayKey];
[[NSUserDefaults standardUserDefaults] synchronize]; // 可选,但确保立即写入磁盘

其他可能的排查点

如果上面的方法没解决问题,可以检查这几个地方:

  • 自定义对象的编码解码是否正确:如果你归档的是自定义对象,必须确保它实现了NSSecureCoding协议,encodeWithCoder:和initWithCoder:方法要正确处理所有属性,否则可能导致解归档后数据丢失或异常。
  • 解归档的类型是否匹配:如果归档的是NSMutableArray,解归档时尽量指定对应的类名;如果解出来是不可变数组,一定要转成可变数组后再操作。
  • 是否有其他代码重置了数组:比如APP启动时、某个回调里有没有重新初始化数组并覆盖存储的情况,这也会导致之前的数据丢失。

可以在关键步骤加日志,比如解归档前后打印数组的count,帮你定位问题:

NSData *existingData = [[NSUserDefaults standardUserDefaults] objectForKey:kSavedArrayKey];
NSLog(@"是否存在已归档数据:%@", existingData ? @"是" : @"否");
if (existingData) {
    NSArray *temp = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:existingData error:nil];
    NSLog(@"解归档后的数组元素数量:%lu", (unsigned long)temp.count);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:54:43