views:

87

answers:

3

I am downloading images in table view cells as they scroll onto the screen. For UX reasons, I start downloading the images in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. I do not wait until the table view is done scrolling. When the table view cell is set, I start downloading images that I do not have already. However, they do not seem to fully download until the table view stops moving. As soon as it stops moving, the images almost download instantly.

Is there anyway to use NSURLConnection where it is not blocked by the main UI thread? Or, is there a way where these images will download very quickly while the table view is being scrolled.

** EDIT **

To prove that NSURLConnection is slower I used NSThread to detach a new selector in a different thread. I then download the data and call back to the main thread where I create a UIImage and show it in the table view. This method works MUCH faster.

Personally, I think that NSURLConnection is getting thrown into the event loop where the UITableView scrolling is blocking it.

A: 

It sounds like you're doing a synchronous download.

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html#//apple_ref/doc/uid/20001836-170129

Read there, and make sure you're using the async APIs

Joshua Weinberg
I am definitely not using the synchronous API's. I think that NSURLConnection gets thrown into the event loop, and the UITableView is taking up all the time in that loop.
rickharrison
+1  A: 

I have experienced this problem before. The asynchronous delegate methods of NSURLConnection are not firing while a scrollView is being scrolled. Although the downloading works in the background, your main thread is not informed of new images. Just like you, I believe the problem is related to scrollviews being scrolled in an inner NSRunLoop with a different RunLoopMode. I have been talking to Apple staff about this and have them look at my code, but we couldn't work out a solution.

On the other hand Jeff LaMarche has this post on his blog, where he does the same thing, and it works as expected. I have not been able to figure out what he does differently (mainly due to not having time), but this may be worth a look.

tonklon
A: 

If you mean "does NSURLConnection execute on the main thread?", then yes, I believe that's the case. The connection is opened and the delegate methods are executed on the main thread. I haven't found any documentation to suggest otherwise, and you can verify it by debugging.

I think your supposition that the UITableView scrolling blocks the NSURLConnection callbacks in the main run loop is correct.

You've already posted one solution, spawning a thread for your selector. Another alternative would be to execute your downloads as NSOperations, which has a couple of benefits:

  • If you force the operations to run concurrently (see Dave Dribin's excellent post on this), you can limit the number of simultaneous downloads, which might be desirable if you have a very large number of images in your table. You say your downloads occur "almost instantly", but that may not be the case if your user is on a slow connection and your table contains a lot of images.
  • You can cancel all the operations if the user does something that makes the image downloads irrelevant, like executing another search.

Dave Dribin's approach, which I use, forces the connections to execute back on the main thread, but that probably isn't necessary for your purposes--you could use your current approach of calling back to the main thread after your images download.

chrispix