In Apple’s MVCNetworking sample code, the NetworkManager class includes this method to maintain a run loop in a secondary thread dedicated to network activity (in order to run NSURLConnection asynchronously):
- (void)networkRunLoopThreadEntry
{
while(YES) {
NSAutoreleasePool *pool;
pool = [[NSAutorelease alloc] init];
[[NSRunLoop currentRunLoop] run];
[pool drain];
}
}
Since the run method exits immediately if there is no source attached to the run loop, this looks like an infinite while loop which is going uselessly to consume CPU resources if there is currently no NSURLConnection attached to the run loop.
On the other hand, to keep the run loop active, some suggests to schedule an empty port in the run loop:
- (void)networkRunLoopThreadEntry
{
NSAutoreleasePool *pool = [[NSAutorelease alloc] init];
NSPort *port = [NSPort port];
[[NSRunLoop currentRunLoop] addPort:port forMode:NSRunLoopCommonModes];
[NSRunLoop run];
[pool drain];
}
However, in this case, my worry is that the run method will never exit, which means the pool will never get drained, which means all objects allocated and autoreleased in the secondary thread will leak.
What is the way to go then?
(For the context, as many others, I’m trying to encapsulate an asynchronous NSURLConnection inside a NSOperation, which means it can be triggered outside of the main thread. Also, the MVCNetworking sample code, as well as the WWDC 2010 sessions Network Apps for iPhone OS, seem to suggest it is a good idea to have a unique secondary thread dedicated to network transfers to prevent latency on the main thread.)
You can create a
CFRunLoopObserverfor thekCFRunLoopBeforeWaitingactivity and add it to the run loop. In the observer’s callout, release the old pool and create a new one. Untested example: