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!

Original source