IOS, NSURLConnection: Delegate callbacks for different threads?

How can I get NSURLConnection to call it to delegate methods from another thread instead of the main thread. I'm trying to mess around with the schedule InRunLoop: forMode: but doesn't seem to do what I want.

I need to upload a large file and it interrupts the main stream so often that some kind of rendering that happens starts to become volatile.

NSURLRequest * request = [NSURLRequest requestWithURL:url]; NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; NSRunLoop * loop = [NSRunLoop currentRunLoop]; NSLog(@"loop mode: %@",[loop currentMode]); [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [connection start]; 

Another thing I don’t see is the Modes. There are only two modes documented, so there are not many for testing.

Any ideas?

thanks

+8
ios nsurlconnection nsrunloop
source share
4 answers

There are several options:

  • In your implementation of delegate methods, use dispatch_async .
  • Run the connection schedule in the background thread.

You can do the latter as follows:

 // all the setup comes here dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSRunLoop *loop = [NSRunLoop currentRunLoop]; [connection scheduleInRunLoop:loop forMode:NSRunLoopCommonModes]; [loop run]; // make sure that you have a running run-loop. }); 

If you want a guarantee on which thread you are using, replace the call with dispatch_get_global_queue() accordingly.

+6
source share

If you want to perform downloads in a separate thread, I am sure that these are the droids you are looking for ...

 - (void) dispatchRequest{ self->finished = NO; NSMutableURLRequest* request = //Formulate your request NSThread* download_thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadThreadLoop:) object:request]; [download_thread start]; } - (void) downloadThreadLoop:(NSMutableURLRequest*) request{ NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; while(!self->finished]){ //This line below is the magic! [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ //... } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ //... } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ //... } - (void)connectionDidFinishLoading:(NSURLConnection *)connection{ //... self->finished = YES; } 
+2
source share

If you really need to load in a new thread, it might be easier to detachNewThreadSelector:toTarget:withObject: configure (and destroy) NSAutoreleasePool , and then use one of the synchronous selectors, e.g. NSData dataWithContentsOfURL: This will not use the asynchronous NSURLConnectionDelegate .

Since this call is synchronous, it will not return until the file is downloaded, which will block the main stream, but since you are in the new stream, this will not happen. Please note that this is generally not recommended. Is there any other code in the main thread that can be optimized?

0
source share

NSURLConnection is already performing asynchronous loading of the main thread. If I understand your question, do you want delegate messages to be sent on a thread other than the main thread? You cannot do this, since you cannot change the internal implementation of NSURLConnection. I can imagine two ways to simulate this.

  • Create a subclass of NSURLConnection (for example, MyURLConnection ) that assigns itself as its own delegate. Note that this creates an intentional save cycle, so be careful. MyURLConnection should define a new delegate that supports NSURLConnectionDelegate . Let me call it finalDelegate . When MyURLConnection processes delegate's own messages, forward them or send them to finalDelegate to any stream you like.

  • Similar to option # 1, but without a subclass. Handle the NSURLConnection delegate NSURLConnection in the main thread and send / send them to any thread you like.

The main difference is that you want a reusable subclass that behaves that way, or that is one implementation.

EDIT: Added suggestion on how to run code in the background

If you are going to process the response in the background, I would either use operations or a large central dispatch. No need to bother with run and create threads. Check out the Apple Concurrency Programming Guide .

0
source share

All Articles