正在调用 – 一个好主意?

是否通常是一个好主意-[NSRunLoop runUntilDate:] ? 它看起来没有任何问题,但是让我感到紧张的是告诉运行循环从运行循环内运行。

更多信息:

我现在有一个项目正在从REST服务中获取数据。 需要获得的关键信息之一是具有有效数据的date范围。 这是一小部分只需要一次获取的数据,所以我决定处理它的最好方法是让属性下载数据,如果局部variablesnil 。 我正在使用ASIHTTPRequest和一个ASINetworkQueue ,所以一切都是asynchronous默认情况下,为了这个工作,这个属性不能返回,直到数据已被下载和处理。 下面是我的代码的大纲,variables的名称已经改变,以保护无辜:

 __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]]; } 

再次,这似乎工作正常。 使用这种方法是否有任何潜在的问题?

除非重叠调用树是完全重入的,否则必须确保不要从可以被调用的运行循环调用的任何方法执行此操作。

Cocoa Touch UI代码没有logging为可重入的(事实上,Apple DTS提供的警告/提示并不是这样),所以如果您的提取数据处理程序可以以任何方式由UI方法(或其他非可以在UI运行循环中调用的redirect代码),不build议从内部调用UI运行循环。

显示某种微调控制器并将其从networking代码中asynchronous完成的事件中解放出来,是不是更好? 喜欢:

 [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]; 

我会考虑这个比运行循环更好。 但是可能你已经知道了这一点,只是想知道runloop解决scheme中有什么确切的缺点?


如果你想阻塞,直到值准备就绪,你可以使用一个信号量:

 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);