如何使异步调用同步

Bes*_*esi 2 architecture iphone ios objective-c-blocks

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

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

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

- (void)assetForURL:(NSURL *)assetURL resultBlock:(ALAssetsLibraryAssetForURLResultBlock)resultBlock failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock;
Run Code Online (Sandbox Code Playgroud)

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

这对我来说似乎是一个非常棘手的设计问题,我看不出如何在没有一些重大黑客的情况下解决这个问题的解决方案.

Tom*_*mmy 5

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

可能你想用一个NSConditionLock来锁定通话assetForUrl:...后立即调用的东西,然后让你的回调解锁它.

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

条件由NSIntegers指定;

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

所以,例如:

NSConditionLock *conditionLock; // somewhere; an instance variable

#define kYourClassInitialCondition 0
#define kYourClassWaitingCondition 1
// etc

...

[conditionLock lockWhenCondition:kYourClassInitialCondition];

[whomever assetForUrl:whatever
          resultBlock:^(args here)
                      {
                         ... do relevant immediate work here ...

                         [conditionLock lockWhenCondition:kYourClassWaitingCondition];
                         [conditionLock unlockWithCondition:kYourClassFinishedCondition];
                      }
          failureBlock:^(args here)
                      {
                         ... as above, same semantics when done ...
                      }
 ];


[conditionLock unlockWithCondition:kYourClassWaitingCondition];

[conditionLock lockWhenCondition:kYourClassFinishedCondition];
[conditionLock unlockWithCondition:kYourClassInitialCondition];
Run Code Online (Sandbox Code Playgroud)

所以,调用线程上的逻辑是:

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

结果块上的逻辑是:

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

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

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

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