拨打-[NSRunLoop runUntilDate:]
通常是个好主意吗?它似乎没有任何问题,但是让我很紧张,告诉运行循环在运行循环中运行。
更多信息:
我现在有一个从REST服务获取数据的项目。需要获得的一个关键信息是具有有效数据的日期范围。这只是一小部分数据,只需要获取一次,因此我认为处理它的最佳方法是让属性在局部变量为nil
时下载数据。我正在使用ASIHTTPRequest
和ASINetworkQueue
,因此默认情况下一切都是异步的,为了使其正常工作,此属性在下载和处理数据之前无法返回。这是我的代码的大纲,变量的名称已被更改以保护无辜:
__block BOOL isWorking = YES;
__block ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:/*actual URL*/] autorelease];
[request setCompletionBlock:^{
// set local variable
isWorking = NO;
}];
[request setFailedBlock:^{
// show alert to user
isWorking = NO;
}];
[queue addOperation:request];
while (isWorking) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
同样,这似乎工作得很好。使用这种方法有任何潜在的问题吗?
答案 0 :(得分:4)
显示某种微调器并将其拆除以响应来自网络代码的异步完成事件不是更好吗?像:
[self displayLoadingSpinner];
[request setCompletionBlock:^{
[self handleSuccess];
dispatch_async(dispatch_get_main_queue(), ^{
[self hideLoadingSpinner];
}];
}];
[request setFailedBlock:^{
[self handleFailure];
dispatch_async(dispatch_get_main_queue(), ^{
[self hideLoadingSpinner];
}];
}];
[queue addOperation:request];
我认为这比使用run循环更好地考虑。但是,你可能已经知道这一点,只是想知道runloop解决方案中存在哪些确切的缺点?
如果要在值准备就绪之前阻止,可以使用信号量:
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[request setCompletionBlock:^{
dispatch_semaphore_signal(sem);
}];
[queue addOperation:request];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_release(sem);
答案 1 :(得分:3)
除非重叠的调用树完全可重入,否则必须确保不要使用您正在调用的运行循环调用的任何方法执行此操作。
Cocoa Touch UI代码没有记录为可重入(事实上,Apple DTS有警告/提示它不是),因此如果您的获取数据处理程序可以通过UI方法以任何方式调用(或者可以在UI运行循环中调用的其他非重入代码),不建议从内部调用UI运行循环。