RequestRetrier Alamofire锁不起作用

时间:2018-07-12 08:07:04

标签: ios swift alamofire

我正在用Alamofire实现RequestRetrier,以刷新给定用户的accessToken。

func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
    lock.lock() ; defer { lock.unlock() }

    if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
        requestsToRetry.append(completion)

        if !isRefreshing {
            refreshToken(completion: { [weak self] succeded, accessToken in

                guard let strongSelf = self else { return }

                strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }

                strongSelf.requestsToRetry.forEach{ $0(succeded, 0.0) }
                strongSelf.requestsToRetry.removeAll()
            })
        }
    } else {
        completion(false, 0.0)
    }
}

调用strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }时,它不会继续执行,因此我遇到了无限循环。我尝试检查strongSelf.lock.try()的结果并返回false。

这是当我使用错误的密码登录时发生的,因此服务器返回了401。

这是我的refreshToken代码

guard !isRefreshing else { return }

// ... Get user ... //
if let user = user {

    isRefreshing = true
    signIn(user: userDTO)
        .subscribe(onNext: { [weak self] userSession in
            guard let strongSelf = self else { return }
            // ... Save accessToken ... //
            completion(true, userSession.accessToken)
            strongSelf.isRefreshing = false
        }, onError: { [weak self] error in
            guard let strongSelf = self else { return }
            // ... Log out user ... //
            completion(false, nil)
            strongSelf.isRefreshing = false
        })
        .disposed(by: bag)
} else {
        completion(false, nil)
}

1 个答案:

答案 0 :(得分:1)

如Github问题https://github.com/Alamofire/Alamofire/issues/2544所示,我可以通过以下方法解决此问题:

workflow Test
{
  $SubscriptionName = Get-AutomationVariable -Name 'VAR-AUTO-SubscriptionName'
  $SubscriptionName 
  $AzureAutomationCredential = Get-AutomationPSCredential -Name 'CRE-AUTO-AutomationUser'
  $AzureAutomationCredential 
}

private let lock = NSLock()

它们之间的区别在于,如果同一线程尝试锁定,则可以解锁递归锁定。