iOS, NSURLConnection: Delegate Callbacks on Different Thread?

后端 未结 4 1419
借酒劲吻你
借酒劲吻你 2020-12-28 10:20

How can I get NSURLConnection to call it\'s delegate methods from a different thread instead of the main thread. I\'m trying to mess around with the scheduleInRunLoop:forMod

相关标签:
4条回答
  • 2020-12-28 10:51

    NSURLConnection is already doing the download off of the main thread asynchronously. If I understand your question, you would like the delegate messages to be sent on a thread other than the main thread? You can't do that as you can't modify the internal implementation of NSURLConnection. I can think of two ways to simulate this.

    1. Create a sublcass of NSURLConnection (e.g. MyURLConnection) that assigns itself as own delegate. Note that this creates an intentional retain cycle so be careful. MyURLConnection should define a new delegate that supports NSURLConnectionDelegate. Let's call this finalDelegate. When MyURLConnection handles it's own delegate messages, forward or dispatch them to finalDelegate on whatever thread you like.

    2. Similar to option #1 but without the subclass. Handle the NSURLConnection delegate methods on the main thread and forward/dispatch them to whatever thread you like.

    The main difference is if you want a reusable subclass that behaves this way or it's a one off 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 grand central dispatch. No need to mess around with run loops and creating threads. Check out Apple's Concurrency Programming Guide.

    0 讨论(0)
  • 2020-12-28 10:54

    If you want to perform downloads on a separate thread, I'm pretty sure these are the droids you're 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;
    }
    
    0 讨论(0)
  • 2020-12-28 11:09

    There are several options:

    1. In your implementation of the delegate methods, make use of dispatch_async.
    2. Start the schedule the connection on a background thread.

    You can do the latter like this:

    // 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're running, replace the call to dispatch_get_global_queue() appropriately.

    0 讨论(0)
  • 2020-12-28 11:14

    If you truly need to do the download in a new thread, it may be easier to detachNewThreadSelector:toTarget:withObject:, setup (and destroy) an NSAutoreleasePool, and then use one of the synchronous selectors like NSData's dataWithContentsOfURL:. This will not make use of the asynchronous NSURLConnectionDelegate.

    Because this call is synchronous, it will not return until the file has been downloaded, which will block the main thread, but because you're in a new thread, it won't. Please note that this is typically discouraged behavior. Is there other code happening in the main thread that can be optimized?

    0 讨论(0)
提交回复
热议问题