views:

548

answers:

2

I'm making an asynchronus POST request in an iPhone app with this call:

    [NSURLConnection connectionWithRequest:req delegate:self];

The request seems to get to the server just fine, but none of the delegate methods get hit. I've implemented:

- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

- (void) connectionDidFinishLoading:(NSURLConnection *)connection

and

- (void) connection:didFailWithError:(NSURLConnection *)connection

None of the log messages for these methods ever appear. The documentation for connectionWithRequest:delegate: says:

delegate

The delegate object for the connection. The delegate will receive delegate messages as the load progresses. Messages to the delegate will be sent on the thread that calls this method. For the connection to work correctly the calling thread’s run loop must be operating in the default run loop mode.

I think the call is being made off of the main thread (is the assumption that, if I didn't start a new thread explicitly, everything runs in one thread correct?), and I checked the thread with this:

CFRunLoopRef loop = CFRunLoopGetMain();
CFStringRef modeString = CFRunLoopCopyCurrentMode(loop);
NSLog(@"The main loop is running in mode: %@", modeString);

Which creates this console output:

2009-09-13 13:32:05.611 Stock Footage[686:20b] The main loop is running in mode: kCFRunLoopDefaultMode

So, that sounds like it is in the default run loop mode. Is there anything else I should look at that could tell me why my delegate methods aren't hit? The delegate is definitely not dying before the request is complete.

Update: CFRunLoopGetCurrent has the mode kCFRunLoopDefaultMode.

Update (5:40 PM Eastern): Well, I've switched to using initWithRequest:delegate: startImmediately in order to get the callbacks going, but I'd still love to see an example of connectionWithRequest:delegate that actually hits the delegate up.

+1  A: 

Two things jump out at me:

  • You have the wrong prototype for your error method (should still get called, however):

connection: (NSURLConnection *) connection didFailWithError: (NSError *) error

  • You should check to make sure you're getting a valid connection back from + connectionWithRequest:delegate:. It's possible it's not even starting the request.
Ben Gottlieb
Thanks. I had the right prototype - I just didn't copy the second line of it. It does seem that I am getting a valid connection - connectionWithRequest:delegate: at least returns a non-nil object.
Jim
How long are you waiting? Is it possible the request is timing out? Have you tried the same request in a browser or other tool?
Ben Gottlieb
I usually wait until I see the results of the post on the web service (Twitter) before giving up on seeing the delegate functions hit, so I don't think it's timing out. FWIW, I've switched to initWithRequest:delegate:startImmediately, and now my delegate callbacks get hit.
Jim
A: 

I had a similar problem. The reason my delegates were not being called is that after I called connectionWithRequest, I started a loop that was checking if the data from the connection had been sent. Since I never returned the control to the RunLoop code, the messages left in the queue were never processed, and therefore the delegate's methods were not called either... Just make sure that you do not do anything heavy after calling connectionWithRequest and everything should work nicely.

Manuel Astudillo