NSURLConnection didReceiveData not called
ios, nsurlconnection, objective-c
Solution
I like to use the sendAsynchronousRequest method.. there's less information during the connection, but the code is a lot cleaner.
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if (data){
//do something with data
}
else if (error)
NSLog(@"%@",error);
}];
From Apple:
By default, a connection is scheduled on the current thread in the default mode when it is created. If you create a connection with the initWithRequest:delegate:startImmediately: method and provide NO for the startImmediately parameter, you can schedule the connection on a different run loop or mode before starting it with the start method. You can schedule a connection on multiple run loops and modes, or on the same run loop in multiple modes.
Unless there is a reason to explicitly run it in [NSRunLoop currentRunLoop], you can remove these two lines:
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];
or change the mode to NSDefaultRunLoopMode
Problem
I've read through tons of messages saying the same thing all over again : when you use a NSURLConnection, delegate methods are not called. I understand that Apple's doc are incomplete and reference deprecated methods, which is a shame, but I can't seem to find a solution. Code for the request is there : ``` // Create request NSURL *urlObj = [NSURL URLWithString:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlObj cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30]; [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; if (![NSURLConnection canHandleRequest:request]) { NSLog(@"Can't handle request..."); return; } // Start connection dispatch_async(dispatch_get_main_queue(), ^{ self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; // Edited }); ``` ...and code for the delegate methods is here : ``` - (void) connection:(NSURLConnection *)_connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"Receiving response: %@, status %d", [(NSHTTPURLResponse*)response allHeaderFields], [(NSHTTPURLResponse*) response statusCode]); self.data = [NSMutableData data]; } - (void) connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error { NSLog(@"Connection failed: %@", error); [self _finish]; } - (void) connection:(NSURLConnection *)_connection didReceiveData:(NSData *)_data { [data appendData:_data]; } - (void)connectionDidFinishDownloading:(NSURLConnection *)_connection destinationURL:(NSURL *) destinationURL { NSLog(@"Connection done!"); [self _finish]; } ``` There's not a lot of error checking here, but I've made sure of a few things : - Whatever happens, `didReceiveData` is never called, so I don't get any data - ...but the data is transfered (I checked using `tcpdump`) - ...and the other methods are called successfully. - If I use the `NSURLConnectionDownloadDelegate` instead of `NSURLConnectionDataDelegate`, everything works but I can't get a hold on the downloaded file (this is a known bug) - The request is not deallocated before completion by bad memory management - Nothing changes if I use a standard HTML page somewhere on the internet as my URL - The request is kicked off from the main queue I don't want to use a third-party library, as, ultimately, these requests are to be included in a library of my own, and I'd like to minimize the dependencies. If I have to, I'll use `CFNetwork` directly, but it will be a huge pain in the you-know-what. If you have any idea, it would help greatly. Thanks!