如何更新代码以解档App Store旧版应用存储的归档数据
旧版NSKeyedArchiver归档数据的兼容读取方案
1. 首先保证存储路径一致
- 旧应用归档数据的存储路径由
dataFilePath方法返回,新版应用Bundle ID不变的前提下,覆盖安装后沙盒数据会完整保留,你需要将旧版dataFilePath的逻辑原封不动迁移到新版,确保读取的路径和旧版写入路径完全一致,这是读取成功的前提。
2. Objective-C新版兼容读取代码
旧版的initForReadingWithData在新iOS版本中已被废弃,你可以用如下兼容代码读取旧数据,和原有逻辑完全等价:
- (void)loadGG { NSString *path = [self dataFilePath]; NSError *error = nil; if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { NSData *data = [NSData dataWithContentsOfFile:path]; // 兼容旧版未启用安全编码的归档数据 NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error]; unarchiver.requiresSecureCoding = NO; gifts = [unarchiver decodeObjectForKey:@"Present"]; [unarchiver finishDecoding]; } else { gifts = [[NSMutableArray alloc] initWithCapacity:20]; } }
如果你的givens/gifts是自定义对象,需要保证自定义类的类名、属性名、NSCoding协议的实现逻辑和旧版完全一致,不要修改编解码对应的key。
3. Swift版读取代码
如果新版用Swift开发,可按如下逻辑读取:
func loadGG() -> [Any]? { guard let path = dataFilePath() as String?, FileManager.default.fileExists(atPath: path), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { return NSMutableArray(capacity: 20) as? [Any] } do { let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) unarchiver.requiresSecureCoding = false let gifts = unarchiver.decodeObject(forKey: "Present") as? [Any] unarchiver.finishDecoding() return gifts } catch { print("解档失败: \(error)") return NSMutableArray(capacity: 20) as? [Any] } }
如果旧版归档的是自定义OC类,Swift对应的类需要添加@objc(旧OC类名)注解,保证类名和旧版一致,避免解档失败。
4. 迁移建议
- 读取到旧数据后,你可以按需将数据迁移到新的存储方案(比如Core Data、SwiftData、plist等),迁移完成后可删除旧归档文件避免冗余。
- 测试时请先安装旧版应用写入测试数据,再用Xcode覆盖安装新版验证读取逻辑,不要直接卸载旧版安装新版,否则沙盒数据会被清空导致读取不到数据。
内容的提问来源于stack exchange,提问作者MPD
相关产品推荐
相关产品推荐

