Software engineer, London UK

NSURLConnection setDelegateQueue is broken on iOS

Dec 29 2011

On Mac OS 10.7 and iOS 5.0, a very handy method has been added to NSURLConnection: setDelegateQueue:.

Using a URL connection in an NSOperation subclass has always been quite tedious because of the fact that one has to run a runloop for as long as the delegate callbacks have to happen. As suggested by Marcus Zarra in this StackOverflow answer, this has usually been achieved by calling CFRunLoopRun() when calling the start: method on NSURLConnection and CFRunLoopStop(CFRunLoopGetCurrent()) when the connection finishes loading or fails.

However, as my colleague Keith Duncan pointed out on CocoaBuilder, this is not optimal and should be avoided.

So, by creating an NSOperationQueue in your NSOperation subclass and scheduling the delegate callbacks into this queue, we do not need to run the current runloop for the length of the operation and consume a thread. In a nutshell, this is very handy and a much cleaner way to achieve this!

Here comes the problem: even though everything works perfectly fine on Lion, when performing the very same thing on iOS, the delegate callbacks are never called. It looks like the connection has to be started (and the delegate queue set) on the main queue for the delegate callbacks to happen. This obviously defeats the point of using it within an NSOperation subclass given that since Snow Leopard (and iOS 4.0) the start method of NSOperation will likely not be called on the main thread.

For this reason, in my opinion, the setDelegateQueue: method is unusable as per iOS 5.0 and should be avoided until Apple fixes this problem.

I have filed a bug at rdar://10529053 and you should dupe it if you observe the same behavior as I do.

I have created a small sample project to demonstrate the bug that I have attached to the radar. Feel free to run it on your side and see for yourself. You can download it from here.

blog comments powered by Disqus