iphone ios thread issue: delegate object not responding when using dispatch_async
Here's my code:
MainDelegate.m
- (BOOL)application:(UIApplication *)application didFinis开发者_JAVA百科hLaunchingWithOptions:(NSDictionary *)launchOptions {
FetchManager *fetchManager = [FetchManager sharedInstance];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0), ^{
[fetchManager fetchData];
});
//regular code continues
}
FetchData.m(this is a singleton class)
- (id)getInstance { ... }
- (void)fetchData
{
NSURL *url = [NSURL URLWithString:@"http://www.data.xml"];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
if (connectionInProgress) {
[connectionInProgress cancel];
[connectionInProgress release];
}
[xmlData release];
xmlData = [[NSMutableData alloc] init];
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
/*and all necessary NSXMLParserDelegate protocol methods are implemented - not shown here*/
Problem: none of the NSXMLParserDelegate protocol methods are fired. I do not know why. If I remove the "dispatch_async" in the didFinishLaunchingWithOptions method, then things are working as expected - the NSXMLParserDelegate protocol methods are fired.
Anyone see the problem?
Two things jump out:
NSURLConnection requires a run loop to operate. When you run on the main thread, there's automatically a run loop that the connection will schedule itself on. When you use dispatch_async(), your block is scheduled in some secondary thread that may not have a run loop, or whose run loop may not be in a mode that allows NSURLConnection to operate.
Even if the connection could schedule itself, the block ends right after the connection is created. NSURLConnection expects send its delegate messages on the thread where it was created, but how would that work if the block has ended? Is there some sort of valid context in which the delegate can be called on that thread?
As stated by Caleb NSURLConnection needs a run loop. One way to accomplish what you want is create a subclass of NSOperation that keeps the loop alive and that manages delegation callbacks. the other way around is use this amazing new Api that just need the creation of an NSOperationQueue, but is only available on iOS5 sendAsynchronousRequest:queue:completionHandler
精彩评论