首页 > 解决方案 > 将数据存储在模型中以便在 Swift 中进行比较

问题描述

expires_in当我刷新我的令牌时,我从我的后端得到一个Int 。

我需要存储令牌到期的日期,并在进行 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但似乎无法轻松转换为日期...

标签: iosswift

解决方案


这里有一个缺陷。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
        }
    }
}

推荐阅读