虽然自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.
答案 0 :(得分:0)
您问“为什么应用程序的执行会在[rLoop run]
停止?” run
方法:
...通过反复调用
NSDefaultRunLoopMode
在runMode:beforeDate:
中运行接收器。换句话说,这种方法有效地开始了一个无限循环,它处理来自运行循环的输入源和定时器的数据。
因此,在网络请求完成之前,您不希望从run
返回。由于您是在后台线程上执行此操作,因此通常不会认为此行为非常严重。
有两种常见的替代方法可以绕过这个问题。一个是AFNetworking的方法,即创建一个专用线程(另一个,除了调度/操作队列使用的线程)。有关此示例,请参阅AFURLConnectionOperation.m
source code。
很多人只会安排网络操作在主队列上运行,例如
[conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
关于你的方法的两个警告:
如果您正在创建自己的运行循环,通常建议您在runloop中添加一个端口以确保它保持不变。 AFNetworking就是这么做的。 The truth about synchronous NSURLConnection也是如此。
或者,run
文档建议
从运行循环中手动删除所有已知输入源和计时器并不能保证运行循环将退出。 OS X可以根据需要安装和删除其他输入源,以处理针对接收者线程的请求。因此,这些来源可以防止运行循环退出。
如果希望运行循环终止,则不应使用此方法。相反,使用其他运行方法之一,并在循环中检查您自己的其他任意条件。一个简单的例子是:
BOOL shouldKeepRunning = YES; // global
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
例如,如果您正在使用基于NSOperation
的解决方案,则需要检查isFinished
。