我正在编写一个类来集中远程调用到我的后端。 调用必须使用oauth进行身份验证,因此在每种方法中,我首先检查我的令牌是否为valide,如果没有,我请求刷新一个。
每种方法都是这样的:
-(void)getRemoteDataAndRun:(nullable void(^)(NSDictionary * __nullable json))success
orFail:(nullable void(^)(AFHTTPRequestOperation * __nullable operation, NSError * __nullable error))failure {
[self checkOAuthTokenAndRun:^{
// my remote call
...
success(json);
} orFail:failure];
}
方法 checkOAuthTokenAndRun 检查令牌有效性并在需要时请求新的令牌。 我的问题是我必须确保不会同时调用checkOAuthTokenAndRun以防止在刷新(写入)时读取凭据。
我尝试使用NSLock但使用块(多线程),我收到以下错误:
*** -[NSLock lock]: deadlock (<NSLock: 0x7ffd9313d9b0> '(null)')
这是完整的checkOAuthTokenAndRun方法:
- (void)checkOAuthTokenAndRun:(void (^)())action orFail:(nullable void(^)(AFHTTPRequestOperation * __nullable operation, NSError * __nullable error))failure
{
NSLog(@"lock oauth check/refresh");
[oauthLock lock];
if (credential == nil || [credential isExpired])
{
NSLog(@"Credentials are null or expired");
if (credential == nil || credential.refreshToken == nil)
{
NSLog(@"Credentials are null or anonymous+expired");
[self getAnonymousCredentialsAndRun:^{
NSLog(@"unlock oauth");
[oauthLock unlock];
action();
} orFail:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nullable error) {
NSLog(@"unlock oauth");
[oauthLock unlock];
failure(operation, error);
}];
}
else
{
NSLog(@"Credentials are expired");
AFOAuth2Manager *OAuth2Manager = [[AFOAuth2Manager alloc] initWithBaseURL:[NSURL URLWithString:BaseURL] clientID:clientId secret:clientSecret];
[OAuth2Manager authenticateUsingOAuthWithURLString:@"/oauth/v2/token" refreshToken:credential.refreshToken success:^(AFOAuthCredential *_credential) {
credential = _credential;
NSLog(@"Received refreshed token");
[AFOAuthCredential storeCredential:credential
withIdentifier:OAuthProviderIdentifier];
NSLog(@"unlock oauth");
[oauthLock unlock];
action();
} failure:^(NSError *error) {
NSLog(@"Failed refreshing oauth token (%@)", [error localizedDescription]);
// remove refresh token
NSLog(@"Unable to get oauth token, delete credentials (%@)", [error localizedDescription]);
[AFOAuthCredential deleteCredentialWithIdentifier:OAuthProviderIdentifier];
credential = nil; //[AFOAuthCredential retrieveCredentialWithIdentifier:OAuthProviderIdentifier];
NSLog(@"unlock oauth");
[oauthLock unlock];
failure(nil, error);
}];
}
}
else { // run the action
NSLog(@"Credentials are valid (%@)", (credential.refreshToken.length ? @"refresh token defined" : @"refresh token not defined"));
NSLog(@"unlock oauth");
[oauthLock unlock];
action();
}
}
如您所见,我正在使用嵌套块,我不知道这是否是我遇到死锁的原因。
再次,我只想阻止 checkOAuthTokenAndRun 方法的并发执行
感谢您的帮助
答案 0 :(得分:0)
网络呼叫是并发的,它们必须是并发的。您的代码的问题是您在另一个本身并发的方法中调用并发方法。解决您的问题:
首先调用方法checkOAuthTokenAndRun,如果成功(来自块的响应),则调用方法getRemoteDataAndRun。
[self checkOAuthTokenAndRun:^{
if(success){
[self getRemoteDataAndRun:^{
}]
}
} orFail:failure];
//上面的代码片段只是解决问题的一个示例。您需要重新设计块参数