views:

49

answers:

1

I kick off a network request, assuming no login credentials are required to talk to the destination server. If they are required, then I get an authentication challenge, at which point I display a view requesting said credentials from the user. When they are supplied, I restart the network request, using those credentials.

That's all fine and dandy, as long as I only do one request at a time. But I'm not, typically.

When both requests are kicked off, I get the first challenge, and present the prompt (using -presentModalViewController:). Then the 2nd challenge comes in. And I crash when it tries to display the 2nd prompt.

I have the bulk of this wrapped in an @synchronized() block, but this has no effect because these delegate methods are all being called on the same (main) thread. The docs say the delegate methods are called on the same thread in which the connection was started. OK, no problem; I'll just write a method that I run on a background thread using -performSelectorInBackground:

NSURLConnection *connection = [[NSURLConnection alloc] 
                               initWithRequest:request 
                                      delegate:self
                              startImmediately:NO];
[connections addObject:connection];
[self performSelectorInBackground:@selector(startConnection:) 
                       withObject:connection];
[connection release];

- (void)startConnection:(NSURLConnection *)connection {
   NSAutoreleasePool *pool = [NSAutoreleasePool new];
   [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                         forMode:NSDefaultRunLoopMode];
   [connection start];
   [pool drain];
}

which should put every network request, and its callbacks, on its own thread, and then my @synchronized() blocks will take effect.

The docs for -initWithRequest:... state "Messages to the delegate will be sent on the thread that calls this method. By default, for the connection to work correctly the calling thread’s run loop must be operating in the default run loop mode." Ok, I'm doing that.

They also state "If you pass NO [for startImmediately], you must schedule the connection in a run loop before starting it." OK, I'm doing that, too.

Furthermore, the docs for NSRunLoop state "Each NSThread object, including the application’s main thread, has an NSRunLoop object automatically created for it as needed. If you need to access the current thread’s run loop, you do so with the class method currentRunLoop." I'm assuming this applies to the background thread created by the call -performSelectorInBackground... (which does appear to be the case, when I execute 'po [NSClassFromString(@"NSRunLoop") currentRunLoop]' in the -startConnection: method).

The -startConnection: method is indeed being called. But after kicking off the connection, I now never get any callbacks on it. None of the -connectionDid… delegate methods. (I even tried explicitly starting the thread's run loop, but that made no difference; I've used threads like this before, and I've never had to start the run loop manually before--but I'm now grasping at straws...)

I think I've come up with a workaround such that I only handle one request at a time, but it's kludgy and I'd like to do this the Right Way. But, what am I missing here?

Thanks! randy

A: 

Is the [pool drain]; line reached? I'm guessing it is. After this the -startConnection method exits, at that point the background thread is finished and destroyed. This is probably not what you want…

You have to run the runloop. You say you did this and it made no difference. This means you did it wrong. Read the Runloop section in the Threaded Programming Guide (It is better to go to the proper docs than hear it off me). Beware, useful methods like -performSelectorInBackground might make multithreading seem appealing, but it is difficult.

Also, what do you mean

'wrapped in an @synchronized() block, but this has no effect because these delegate methods are all being called on the same (main) thread'

?

@synchronized() will do the same on the main thread as it does on a background thread.. what do you think it does?

mustISignUp