我正在重写回调方法以处理 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;
由于我处于同步方法中,因此在获得数据之前我无法“离开”该方法。另外,我无法预加载所需的数据,因为在进入请求之前我不知道需要哪个 Assets 。
这对我来说似乎是一个相当棘手的设计问题,我看不到如何在不进行一些重大修改的情况下解决这个问题的解决方案。
最佳答案
编辑:stevex 是绝对正确的,你的首要任务应该是找到一种方法来使整个事情异步。如果做不到这一点,下面的答案应该可以实现您想要的,同时将同步步骤委托(delegate)给操作系统以实现最佳电源使用。
您可能希望在调用后立即使用 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];
因此,调用线程上的逻辑是:
- 在初始条件下获取锁
- 发出 URL 获取请求
- 释放等待状态的锁
- 在完成状态下获取锁
- 在初始条件下释放锁
结果 block 上的逻辑是:
- 在等待状态下获取锁
- 在完成状态下释放锁定
结果 block 将阻塞,直到调用线程将条件锁置于等待条件中。因此,如果回调是立即的,那么排序就没有问题。
建立等待条件后,调用线程将阻塞,直到完成条件中释放条件锁。因此,如果结果 block 尚未完成,那么它应该等待结果 block 完成。
当然,这是假设您的结果 block 是由被调用者通过 GCD 分派(dispatch)的,或者如果调用内联,则从单独的线程调用。前者可能是一个安全的假设。
关于iphone - 如何使异步调用同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8506091/