NSURLConnection是否阻止主/ UI线程

时间:2010-07-13 03:47:24

标签: iphone objective-c ipad nsurlconnection

我在桌面视图单元格中下载图像,因为它们滚动到屏幕上。出于UX原因,我开始在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath下载图像。我不要等到表格视图完成滚动。设置表格视图单元格后,我开始下载我还没有的图像。但是,在表视图停止移动之前,它们似乎没有完全下载。一旦它停止移动,图像几乎立即下载。

是否有使用NSURLConnection的地方没有被主UI线程阻止?或者,是否有一种方法可以在滚动表格视图时非常快速地下载这些图像。

**编辑**

为了证明NSURLConnection较慢,我使用NSThread在另一个线程中分离新的选择器。然后我下载数据并回调主线程,在那里我创建了一个UIImage并在表视图中显示它。这种方法工作得更快。

就个人而言,我认为NSURLConnection被抛入事件循环,UITableView滚动阻止了它。

4 个答案:

答案 0 :(得分:22)

阅读NSDefaultRunLoopMode vs NSRunLoopCommonModes以获得有关所有下载委托通知排队的原因的详细说明,但是在使用主线程更改时滚动下载:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
                                                              delegate:self];

到此:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
                                                              delegate:self
                                                      startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
                      forMode:NSRunLoopCommonModes];
[connection start];

答案 1 :(得分:2)

我之前遇到过这个问题。在滚动scrollView时,NSURLConnection的异步委托方法不会触发。虽然下载在后台运行,但主线程不会通知新图像。就像你一样,我相信这个问题与在内部NSRunLoop中使用不同的RunLoopMode滚动滚动视图有关。我一直在与Apple工作人员讨论这个问题并让他们查看我的代码,但我们无法找到解决方案。

另一方面,Jeff LaMarche在他的博客上有this post,他做同样的事情,并且按预期工作。我无法弄清楚他的做法有多么不同(主要是由于没有时间),但这可能值得一看。

答案 2 :(得分:1)

如果你的意思是“NSURLConnection是否在主线程上执行?”,那么是的,我相信是这样的。打开连接,并在主线程上执行委托方法。我没有找到任何其他建议的文档,您可以通过调试来验证它。

我认为您认为UITableView滚动阻止主运行循环中的NSURLConnection回调是正确的。

您已经发布了一个解决方案,为您的选择器生成一个线程。另一种选择是将您的下载作为NSOperations执行,这有几个好处:

  • 如果强制操作同时运行(请参阅Dave Dribin's excellent post on this),则可以限制同时下载的数量,如果表格中包含大量图像,则可能需要这样做。您说您的下载几乎是“即时”发生,但如果您的用户连接速度很慢且您的表中包含大量图片,则情况可能并非如此。
  • 如果用户执行了使图像下载无关的操作,例如执行其他搜索,则可以取消所有操作。

我使用Dave Dribin的方法强制连接在主线程上执行,但这可能不是出于您的目的 - 您可以使用当前的方法在图像之后回调主线程下载。

答案 3 :(得分:-1)