我有一个函数可以在URLSession上提供一层。调用此函数时,我想检查当前访问令牌是否已过期(如果已过期),我将暂停当前调用,进行调用以请求新令牌,替换钥匙串中的现有条目,然后继续执行以下操作电话。
android:gravity="center"
已存在一种用于处理钥匙串的机制,因此请假定此机制已经到位。
请求新令牌的功能看起来像
CoordinatorLayout
我希望执行程序在这里暂停
func profile(with endpoint: ProfilesEndpoint, method: HTTPMethod, body: String?, headers: [String: String]?, useAuthToken: Bool = true, completion: @escaping (Either<ProfileResponse>) -> Void) {
var request = endpoint.request
request.httpMethod = method.rawValue
if let body = body {
request.httpBody = body.data(using: .utf8)
}
if useAuthToken {
if !AuthService.shared.isTokenValid {
let group = DispatchGroup()
group.enter()
OAuthService.shared.requestRefreshToken()
group.leave()
}
let (header, token) = AuthService.shared.createAuthHeaderForNetworkRequest()
request.addValue(token, forHTTPHeaderField: header)
}
if let headers = headers {
for (key, value) in headers {
request.addValue(value, forHTTPHeaderField: key)
}
}
execute(with: request, completion: completion)
}
但是没有。
在完成其余功能之前,我如何等待此调用完成?
答案 0 :(得分:0)
添加到您的requestRefreshToken
方法完成处理程序中,该处理程序将在您完成令牌请求后执行
func requestRefreshToken(_ completion: @escaping () -> Void) {
if let refreshToken = KeychainWrapper.standard.string(forKey: "RefreshToken") {
var postBody = "grant_type=\(refreshTokenGrantType)&"
postBody += "client_id=\(clientId)&"
postBody += "refresh_token=\(refreshToken)&"
let additionalHeaders = [
"Content-Type": "application/x-www-form-urlencoded;"
]
APIClient.shared.identity(with: .token, method: .post, body: postBody, headers: additionalHeaders, useAuthToken: false) { either in
switch either {
case .success(let results):
guard let accessToken = results.accessToken, let refreshToken = results.refreshToken else {
completion()
return
}
AuthService.shared.addTokensToKeyChain(tokens: ["AccessToken": accessToken, "RefreshToken": refreshToken])
case .error(let error):
print("Error:", error)
}
completion()
}
}
}
然后将dispatchGroup
保留为关闭状态,并添加group.wait()
(在调用请求方法之后)以暂停当前线程,直到组的任务完成
group.enter()
OAuthService.shared.requestRefreshToken {
group.leave()
}
group.wait()
注意:您可以在完成时添加布尔参数,以检查令牌请求是否成功
答案 1 :(得分:0)
为什么不在下面而不是在上面?这似乎是NSURLProtocol
的理想用法。基本上:
NSURLSession
实例并将其存储在属性中。该会话应不配置为使用协议,否则您将陷入无限循环。采用这种方法,除了在创建新会话时需要将协议添加到会话配置中的protocolClasses
之外,整个身份验证过程对应用程序基本上是透明的。
(有许多网站,包括developer.apple.com,提供了自定义NSURLProtocol
子类的示例;如果您决定采用这种方法,则可能应使用其中一个示例代码项目作为一个起点。)
或者,如果您想坚持使用顶层方法,则需要停止考虑“停止”方法的执行,而应将其视为“稍后再做方法的最后一部分”。都是关于异步思考的。
基本上: