继承OIDAuthState的子类无法被NSKeyedArchiver归档的问题排查
问题分析与修复
你的代码核心问题是把编码和解码的逻辑完全写反了:
required init?(coder: NSCoder)是解码方法,用于从归档数据中恢复对象属性,应该在这里读取coder中的值,而非写入。override func encode(with coder: NSCoder)是编码方法,用于将对象属性写入归档数据,应该在这里把属性编码到coder中,而非读取。
你当前的代码在解码方法里调用coder.encode,在编码方法里调用coder.decodeBool,这会导致归档时(调用encode(with:))尝试用NSKeyedArchiver执行解码操作,但NSKeyedArchiver并没有decodeBoolForKey:方法,因此抛出错误。
修复后的代码
class AuthenticationStateManager: OIDAuthState, AuthenticationState { var isExpiredTokenEnforced = false var lastTokenResponseInterface: TokenResponse? { if isExpiredTokenEnforced { return EnforcedExpiredTokenResponse(idToken: super.lastTokenResponse?.idToken, accessToken: super.lastTokenResponse?.accessToken) } else { return super.lastTokenResponse } } override static var supportsSecureCoding: Bool { true } required override init(authorizationResponse: OIDAuthorizationResponse?, tokenResponse: OIDTokenResponse?, registrationResponse: OIDRegistrationResponse?) { super.init(authorizationResponse: authorizationResponse, tokenResponse: tokenResponse, registrationResponse: registrationResponse) } required init?(coder: NSCoder) { // 解码:从coder中读取属性值 self.isExpiredTokenEnforced = coder.decodeBool(forKey: "isExpiredTokenEnforced") super.init(coder: coder) } override func encode(with coder: NSCoder) { // 编码:将属性值写入coder coder.encode(isExpiredTokenEnforced, forKey: "isExpiredTokenEnforced") super.encode(with: coder) } }
额外说明
- 遵循
NSSecureCoding协议时,编码时写入的key,解码时必须使用相同的key读取,保证逻辑对应。 - 解码时需先处理子类属性,再调用父类的
init(coder:);编码时需先调用父类的encode(with:),再处理子类属性,确保父类属性能正确被处理。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

