dispatch_queue_t中的NSURL连接



尽管自iOS 4.0发布以来,这个问题已经被问了很多次,但我仍然无法找到NSURLConnection的委托方法的解决方案,该方法没有在GCD队列中调用。生成NSURLConnection的代码如下:

NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:nil delegate:self startImmediately:NO];
NSRunLoop* rLoop = [NSRunLoop currentRunLoop];
[conn scheduleInRunLoop:rLoop forMode:NSRunLoopCommonModes];
[conn start];
[rLoop run];

为什么应用程序在上停止执行

[rLoop run];

使得这一行之后的代码的执行被延迟。

此外,此代码在iOS模拟器7.0上运行良好,但在iOS 7设备上则不然。有人能解释一下原因吗??对于使用NSURLConnection的后台下载,接收到的响应也需要在后台处理。我还需要在mainRunLoop上安排NSURLConnection吗?

编辑:由于NSURLConnection是在后台线程中创建的,该线程可能没有关联的NSRunLoop,因此下面的代码可以工作吗?

[NSRunLoop currentRunLoop]; // This will create a runLoop if not already present for the current thread.
self.conn = [NSURLConnection alloc] initWithRequest:req delegate:self];// This will automatically schedule the NSURLConnection in above created runLoop and thus divert the events to get associated with delegates for NSURLConnection.

您会问"为什么应用程序在[rLoop run]上停止执行?"run方法:

。。。通过重复调用CCD_ 4来在CCD_。换句话说,这种方法有效地开始了一个无限循环,该循环处理来自运行循环的输入源和计时器的数据。

因此,在完成网络请求之前,您预计不会从run返回。由于您是在后台线程上执行此操作,因此通常不会认为此行为存在严重问题。

有两种常见的替代方案可以绕过这个问题。一种是AFNetworking的方法,它是创建一个专用线程(除了调度/操作队列使用的线程之外,还有另一种)。请参阅AFURLConnectionOperation.m源代码中的一个示例。

很多人只会将网络操作安排在主队列上运行,例如

[conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

关于您的方法的两个注意事项:

  1. 如果你正在创建自己的运行循环,通常建议你在运行循环中添加一个端口,以确保它保持不变。AFNetworking就是这样做的。同步NSURLConnection的真相也是如此。

  2. 或者,run文件表明

    手动从运行循环中删除所有已知的输入源和计时器并不能保证运行循环将退出。OSX可以根据需要安装和删除额外的输入源,以处理针对接收器线程的请求。因此,这些源可以阻止运行循环退出。

    如果希望终止运行循环,则不应该使用此方法。相反,使用其他运行方法之一,并在循环中检查您自己的其他任意条件。一个简单的例子是:

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

    例如,如果您正在执行基于NSOperation的解决方案,则需要检查isFinished

最新更新