提问者:小点点

在Swift中将数据存储在模型中以便比较


当我刷新令牌时,我从后端获得一个expires_inInt。

我需要存储令牌到期的日期,并在调用API之前检查它。

所以我的模型是这样的:

    struct TokenModel: Codable {
        var access_token: String
        var refresh_token: String
        var token_type: String
        var expires_in: Int
        var scope: String

        var expires: Date? {
            let now = Date()
            let calendar = Calendar.current
            return calendar.date(byAdding: .second, value: expires_in, to: now)
        }
    }

然后根据当前日期检查expires

让我担心的是日历参数。 用户是否可以更改设备或日历上的日期/时间,然后逻辑将不工作?

我想转换为ISO8601formatter,但似乎无法轻松转换到目前为止。。。


共1个答案

匿名用户

这里有个缺陷。 expires不返回真正的截止日期。 它现在总是返回+expires_in秒。 那个日期永远在未来。

一种可能的解决方法是标记实例的创建时间。

struct TokenModel: Codable {
    var access_token: String
    var refresh_token: String
    var token_type: String
    var expires_in: Int
    var scope: String

    let startingDate = Date()
    var expires: Date? {
        let calendar = Calendar.current
        return calendar.date(byAdding: .second, value: expires_in, to: startingDate)
    }
}

这也有问题。 不小心处理TokenModel实例可能会导致其他缺陷。

如果服务器提供了过期时间,那么您可能会遇到时间漂移的问题。 如果服务器关闭了几秒,或者如果客户端从标准时间关闭了几秒,那么过期时间就关闭了。

我用过几次的解决方案是把责任分开。 创建单独的授权管理器。

struct TokenModel: Codable {
    let access_token: String
    let refresh_token: String
    let token_type: String
    let expires_in: Int
    let scope: String
}

class AuthorizationManager {
    var accessToken: String?
    var refreshToken: String?
    var tokenType: String?
    var expiration: Date?
    var scope: String?

    lazy var calendar: Calendar = .current

    func update(token: TokenModel) {
        if let tokenExpiration = calendar.date(byAdding: .second, value: token.expires_in, to: Date()) {
            accessToken = token.access_token
            refreshToken = token.refresh_token
            tokenType = token.token_type
            expiration = tokenExpiration
            scope = token.scope
        }
    }
}