如何使异步调用同步

时间:2011-12-14 14:27:45

标签: iphone ios architecture objective-c-blocks

我重写了一个回调方法,以便处理HTTP请求的响应。

-(NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path{
    NSObject <HTTPResponse> *response;
    // Here I should load the data
}

但是,在我的请求中,我必须加载一些只能异步工作的数据:

- (void)assetForURL:(NSURL *)assetURL resultBlock:(ALAssetsLibraryAssetForURLResultBlock)resultBlock failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock;

由于我处于同步方法中,所以在获取数据之前我不能“离开”方法。此外,我无法预加载所需的数据,因为我在请求之前不知道需要哪个资产。

这对我来说似乎是一个非常棘手的设计问题,如果没有一些重大的黑客攻击,我无法找到解决方法。

1 个答案:

答案 0 :(得分:5)

编辑:stevex是绝对正确的,你的首要任务应该是找到一种方法来使整个事情异步。如果做不到这一点,下面的答案应该实现你想要的,同时委托同步步骤到操作系统,以实现最佳的用电量。

您可能希望在通话结束后立即使用NSConditionLock来锁定调用{​​{1}}的内容,然后让您的回调解锁。

条件锁是具有条件的锁。所以你说'当条件是X时我想要锁'并且你的线程阻塞直到它处于那种状态。然后锁定,直到你解锁它,然后你可以在解锁后立即指定它将处于什么状态。

使用NSIntegers指定条件;

所以锁内置了一个通信方面。

所以,例如:

assetForUrl:...

因此,调用线程上的逻辑是:

  • 在初始条件下获得锁定
  • 发出网址提取请求
  • 在等待状态下释放锁定
  • 获得完成状态的锁定
  • 在初始条件下释放锁定

结果块上的逻辑是:

  • 在等待状态下获取锁定
  • 在完成状态下释放锁定

结果块将阻塞,直到调用线程将条件锁定置于等待状态。因此,如果回调是立即的,那么排序没有问题。

在建立等待条件之后,调用线程将阻塞,直到在完成条件中释放条件锁定。因此,如果尚未完成结果块,则应等待结果块完成。

当然,这假定您的结果块由被调用者通过GCD分派,或者如果从单独的线程调用内联调用。前者可能是一个安全的假设。