UserDefaults解码失败:仅支持适配NSSecureCoding的类
问题解决方法
原因分析
你使用的NSKeyedUnarchiver.unarchivedObject(ofClass:from:)是苹果推出的安全解码API,它强制要求解码的类必须遵循NSSecureCoding协议。但你的PlayerClass仅实现了旧的NSCoding协议,且保存数据时开启了requiringSecureCoding: false生成非安全编码数据,因此解码时触发报错。
方案一:兼容旧编码(快速临时解决)
直接替换解码代码为旧的非安全解码方法,同时做好类型转换:
if let dataToRetrieve = UserDefaults.standard.data(forKey: "currentPlayerToon") { do { guard let returnedPlayerInformation = NSKeyedUnarchiver.unarchiveObject(with: dataToRetrieve) as? PlayerClass else { print("类型转换失败") return } print("Success") } catch { print(error) } }
⚠️ 注意:苹果不推荐这种方式,存在安全风险,仅作为临时兼容方案。
方案二:升级为安全编码(官方推荐)
从编码到解码全程遵循苹果安全规范,这是长期维护的最优解:
1. 修改类声明,遵循NSSecureCoding
补充实现supportsSecureCoding静态属性,并重写编码解码方法:
class PlayerClass: NSObject, NSSecureCoding { static var supportsSecureCoding: Bool { return true } var toonName: String // 自定义初始化方法 init(toonName: String) { self.toonName = toonName super.init() } // 解码方法(NSSecureCoding要求) required init?(coder: NSCoder) { guard let toonName = coder.decodeObject(forKey: "toonName") as? String else { return nil } self.toonName = toonName super.init() } // 编码方法(NSSecureCoding要求) func encode(with coder: NSCoder) { coder.encode(toonName, forKey: "toonName") } }
2. 修改保存代码,启用安全编码
将requiringSecureCoding参数改为true:
do { let dataToSave = try NSKeyedArchiver.archivedData(withRootObject: cachedToonToSave, requiringSecureCoding: true) UserDefaults.standard.set(dataToSave, forKey: "currentPlayerToon") print("saving worked") } catch { print("saving failed") }
3. 解码代码保持不变
此时原有的安全解码方法可正常执行:
if let dataToRetrieve = UserDefaults.standard.data(forKey: "currentPlayerToon") { do { let returnedPlayerInformation = try NSKeyedUnarchiver.unarchivedObject(ofClass: PlayerClass.self, from: dataToRetrieve) print("Success") } catch { print(error) } }
内容的提问来源于stack exchange,提问作者Mason Ballowe
相关产品推荐
相关产品推荐

