ios - NSOperation 和 NSURLConnection

标签 ios objective-c nsoperation nsoperationqueue

我有一个操作“A”,它使用异步 NSURLConnection 从 Web 服务中检索 ID 列表。当收到响应时,操作循环遍历这些 ID 并为每个 ID 创建一个操作“B”并将它们添加到队列中。

当我将 maxConcurrentOperationCount 设置为 1 开始测试时,我只能执行 A 操作。所以似乎添加到队列中的“B”操作仍在等待“A”完成。

“executing”和“finished”属性已正确更新,“isFinished”上的 KVO 通知按预期工作,但队列仍包含 2 个操作,“A”操作永远不会被删除。

我试图通过“performSelectorOnMainThread: @selector(start)”更改在 NSRunLoop 中调度连接的代码,它解决了这个问题,但它创建了另一个问题。当执行操作“B”时,根据服务器响应,它们可以通过调用它们的“开始”方法而不是将它们添加到队列来启动其他非并发操作“C”,在这种情况下我需要那个“B”在“C”完成之前不会完成(这就是为什么我使用“开始”而不是将“C”添加到队列中),并且我不想在主线程上执行“C”这就是正在发生的事情当我使用“performSelectorOnMainThread”时。

如果有人可以帮助我解决 runloop 代码的问题,我尝试查看 AFNetworking 和其他库,但我看不出我做错了什么。

- (void)send
{
    serverConnection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate: self startImmediately: NO];
    port = [NSPort port];
    runLoop = [NSRunLoop currentRunLoop];
    [runLoop addPort: port forMode: NSDefaultRunLoopMode];
    [serverConnection scheduleInRunLoop: runLoop forMode: NSDefaultRunLoopMode];
    [serverConnection start];
    [runLoop run];
}


- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)theError
{
    [runLoop removePort: port forMode: NSRunLoopCommonModes];
 // code handling error
}


- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
{
    [runLoop removePort: port forMode: NSRunLoopCommonModes];
 // code processing response
 // If this is executed on main thread, non-concurrent operations created and started from the response processing code, 
 // will be executed on main thread, instead of using the thread that was dedicated to this operation. 
}

最佳答案

根据NSRunLoop方法run的文档:

Manually removing all known input sources and timers from the run loop is not a guarantee that the run loop will exit. OS X can install and remove additional input sources as needed to process requests targeted at the receiver’s thread. Those sources could therefore prevent the run loop from exiting.

If you want the run loop to terminate, you shouldn't use this method. Instead, use one of the other run methods and also check other arbitrary conditions of your own, in a loop. A simple example would be:

    BOOL shouldKeepRunning = YES;        // global
    NSRunLoop *theRL = [NSRunLoop currentRunLoop];
    while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);

where shouldKeepRunning is set to NO somewhere else in the program.

显然,您可以使用 ![self isFinished] 而不是使用 shouldKeepRunning,但它说明了这一点。

如果您要启用多个并发操作(并且为了高效运行所有 B 请求,您应该认真考虑这一点),您可能想看看 AFNetworking 做了什么,它是(a ) 为网络请求创建一个专用线程并在那里启动运行循环,(b) 在此运行循环上安排所有网络请求; (c) 使操作并发(例如 isConcurrent 返回 YES)。

关于ios - NSOperation 和 NSURLConnection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22766564/

相关文章:

iphone - 如何判断 NSOperation 已经执行了多长时间?

ios - Swift 并发操作慢 2 倍

ios - AFNetworking 和处理 NSOperationQueue - 在完成时执行代码并跟踪进度

ios - iPhone 相机,如何避免预览 View 上的相机叠加;如何知道何时进入预览 View ?

iphone - 在 iPhone 上发送 UDP 数据包在新的 3G 连接上失败,但在其他情况下有效

ios - 如何在 iOS 中将数据从容器发送到父 View Controller ?

objective-c - 如何让 Xcode 先打开 .h 而不是 .m 文件?

ios - daisy NSOperation main 进入 super 可以接受吗?

c# - Xamarin.Forms(可移植)解决方案中的 Xamarin.Mac 项目

objective-c - 为什么 NSOperations 和 sleep 不能正常工作?