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

继承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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:01:08