如何替换废弃的NSKeyedUnarchiver方法并兼容现有iOS用户?
替换废弃的NSKeyedArchiver/Unarchiver方法,兼容现有用户实现方案
问题背景
现有iOS应用通过UserDefaults存储登录用户数据,当前使用的NSKeyedUnarchiver.unarchiveObject(with:)和NSKeyedArchiver.archivedData(withRootObject:)从iOS 12起已被废弃,虽仍能在新版本iOS运行,但需替换为Apple推荐的安全编码方法,同时不能影响现有用户的已存数据。现有代码如下:
static var userLoginResponse : LoginModel? { get { if let data = UserDefaults.standard.data(forKey: "userLoginResponse"), let respData = NSKeyedUnarchiver.unarchiveObject(with: data) as? Data { return LoginModel(data: respData) } return nil } set { if let value = newValue?.toJsonData() { UserDefaults.standard.setValue(NSKeyedArchiver.archivedData(withRootObject: value), forKey: "userLoginResponse") } else { UserDefaults.standard.setValue(nil, forKey: "userLoginResponse") } } }
修改思路
- 写入逻辑:直接替换为新的
archivedData(withRootObject:requiringSecureCoding:error:)方法,启用安全编码(Data默认支持安全编码),同时处理归档错误。 - 读取逻辑:优先尝试用新的
unarchivedObject(ofClass:from:)方法解码,若失败(说明是老方法存储的数据),再降级使用废弃的老方法解码,确保兼容现有用户数据。
修改后的代码
static var userLoginResponse: LoginModel? { get { guard let data = UserDefaults.standard.data(forKey: "userLoginResponse") else { return nil } // 优先尝试新方法解码 do { if let respData = try NSKeyedUnarchiver.unarchivedObject(ofClass: Data.self, from: data) { return LoginModel(data: respData) } } catch { // 新方法解码失败,用老方法兼容旧数据 if let respData = NSKeyedUnarchiver.unarchiveObject(with: data) as? Data { return LoginModel(data: respData) } } return nil } set { guard let value = newValue?.toJsonData() else { UserDefaults.standard.setValue(nil, forKey: "userLoginResponse") return } do { // 使用新的归档方法,启用安全编码 let archivedData = try NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true) UserDefaults.standard.setValue(archivedData, forKey: "userLoginResponse") } catch { // 归档失败时做兜底处理 UserDefaults.standard.setValue(nil, forKey: "userLoginResponse") print("归档用户数据失败:\(error.localizedDescription)") } } }
关键说明
- 安全编码:新方法强制要求启用安全编码(
requiringSecureCoding: true),Data类本身已经遵循NSSecureCoding协议,无需额外处理。 - 兼容逻辑:读取时先尝试新方法,失败后回退到老方法,保证已用老版本应用存储的用户数据仍能正常读取。
- 错误处理:新增了
do-catch块处理归档和解档过程中的错误,提升代码稳定性,避免崩溃。
内容的提问来源于stack exchange,提问作者RP89
相关产品推荐
相关产品推荐

