我使用以下方法尝试在10秒内同步获取OAuth访问令牌,否则返回nil。它工作正常,但作为练习我想转换我的代码使用信号量。
Runloop版本
- (NSString*)oAuthAccessToken
{
@synchronized (self)
{
NSString* token = nil;
_authenticationError = nil;
if (_authentication.accessToken)
{
token = [NSString stringWithFormat:@"Bearer %@", _authentication.accessToken];
}
else
{
[GTMOAuth2ViewControllerTouch authorizeFromKeychainForName:_keychainName authentication:_authentication];
[_authentication authorizeRequest:nil delegate:self didFinishSelector:@selector(authentication:request:finishedWithError:)];
for (int i = 0; i < 5; i++)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
if (_authentication.accessToken)
{
token = [NSString stringWithFormat:@"Bearer %@", _authentication.accessToken];
break;
}
else if (_authenticationError)
{
break;
}
}
}
// LogDebug(@"Returning token: %@", token);
return token;
}
}
信号量版
代码的信号量版本有点像这样:
- (NSString*)oAuthAccessToken
{
@synchronized (self)
{
NSString* token = nil;
_authenticationError = nil;
if (_authentication.accessToken)
{
token = [NSString stringWithFormat:@"Bearer %@", _authentication.accessToken];
}
else
{
_authorizationSemaphore = dispatch_semaphore_create(0);
dispatch_async(_authorizationRequestQueue, ^(void)
{
[GTMOAuth2ViewControllerTouch authorizeFromKeychainForName:_keychainName authentication:_authentication];
[_authentication authorizeRequest:nil delegate:self didFinishSelector:@selector(authentication:request:finishedWithError:)];
});
dispatch_semaphore_wait(_authorizationSemaphore, DISPATCH_TIME_FOREVER);
if (_authentication.accessToken)
{
token = [NSString stringWithFormat:@"Bearer %@", _authentication.accessToken];
}
}
return token;
}
}
疑难杂症!!! GTMOAuth2有时会立即返回
在后一种情况下如何发信号通知我的信号量?如果我向authentication.assessToken添加一个观察者,它会被触发吗?
答案 0 :(得分:3)
我不熟悉GTMOAuth2库,但authentication.accessToken
是一个属性,因此似乎没有任何东西阻止它与KVO兼容。在所有情况下,添加观察者应该适用于异步和同步。因此,我只考虑异步情况。
如果您想让您的解决方案更加清洁,那么您一定要尝试Reactive Cocoa。