I like the smell of Swift in the morning…

NSURLConnection: How to avoid blocked file loading during scrolling of UIScrollView or UITableView

Posted: | Author: | Filed under: iOS | Tags: , , | 10 Comments »

When you want to load a file (like a large image) into your app, you don’t want to block the user interface during the loading. It’s always a good idea to load large files asynchronously.

The easiest way to load a file in the background is via NSURLConnection.

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

However, if you use the default settings the connection object will be scheduled in the NSDefaultRunLoopMode. That means that the connection is only executing the request when the app’s run loop is in NSDefaultRunLoopMode.

Now, when a user touches the screen (e.g. to scroll a UIScrollView) the run loop’s mode will be switched to NSEventTrackingRunLoopMode. And now, that the run loop is not in NSDefaultRunMode anymore, the connection will not execute. The ugly effect of that is, that the download is blocked whenever the user touches the screen. And that can be a looong time when the user is scrolling a UITableView, because the download is stopped until the scrolling completely stops. And when the user continues to scroll, the download is blocked again.

Fortunately the solution to this problem is quite simple: You can schedule the connection in another NSRunLoopMode. When you schedule the connection in NSRunLoopCommonModes it will execute in all run loop modes (that have been declared as a member of the set of “common” modes, to be precise). That means that the connection is not only working in NSDefaultRunLoopMode but also in NSEventTrackingRunLoopMode (when the user touches the screen).

[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 

Bingo! The async file loading is not blocked anymore during user interaction.