首页 > 解决方案 > RequestRetrier 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)
}

标签: iosswiftalamofire

解决方案


如 Github 问题https://github.com/Alamofire/Alamofire/issues/2544中所见,我可以通过更改来解决此问题:

private let lock = NSLock()

private let lock = NSRecursiveLock()

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


推荐阅读