用观察者来发信号?

时间:2013-09-26 09:37:33

标签: ios objective-c grand-central-dispatch reactive-cocoa gtm-oauth2

我使用以下方法尝试在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有时会立即返回

  • 当GTMOAuth2需要访问网络时,它会通过委托方法回调。在这种方法中,我发信号通知我的信号量。
  • 有时GTMOAuth2能够立即返回。问题是方法返回void。

在后一种情况下如何发信号通知我的信号量?如果我向authentication.assessToken添加一个观察者,它会被触发吗?

1 个答案:

答案 0 :(得分:3)

我不熟悉GTMOAuth2库,但authentication.accessToken是一个属性,因此似乎没有任何东西阻止它与KVO兼容。在所有情况下,添加观察者应该适用于异步和同步。因此,我只考虑异步情况。

如果您想让您的解决方案更加清洁,那么您一定要尝试Reactive Cocoa