9

打电话通常是个好主意-[NSRunLoop runUntilDate:]吗?它似乎可以正常工作,但是告诉运行循环从运行循环中运行让我感到紧张。

更多信息:

我现在有一个从 REST 服务获取数据的项目。需要获取的一项关键信息是具有有效数据的日期范围。这是一小部分数据,只需要获取一次,所以我决定处理它的最佳方法是让属性下载数据,如果局部变量是nil. 我正在使用ASIHTTPRequestand 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]];
}

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

4

2 回答 2

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

我认为这比使用运行循环更好。但可能您已经知道这一点,只是想知道 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);
于 2011-02-07T17:59:32.410 回答
3

您必须确保不要从您正在调用的运行循环可能调用的任何方法中执行此操作,除非重叠的调用树是完全可重入的。

Cocoa Touch UI 代码未记录为可重入(事实上,Apple DTS 有警告/提示不是),因此如果您的获取数据处理程序可以以任何方式由 UI 方法(或其他非- 可在 UI 运行循环中调用的可重入代码),不建议从其内部调用 UI 运行循环。

于 2011-02-07T17:46:30.023 回答