Asynchronous NSURLConnection on separate thread fails to call delegate methods
Asked Answered
L

2

6

I am running a NSURLConnection on a separate thread (I am aware that it is asynchronous and works when running on the main thread), but it is not making delegate calls even when I pass the parent thread as the delegate. Does anyone know how to do this?

Code:

-(void)startConnectionWithUrlPath:(NSString*)URLpath {

//initiates the download connection - setup
NSURL *myURL = [[NSURL alloc] initWithString:URLpath];

myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[myURL release];


//initiates the download connection on a seperate thread
[NSThread detachNewThreadSelector:@selector(startDownloading:) toTarget:self withObject:self];

}


-(void)startDownloading:(id)parentThread {

 NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];

 [NSURLConnection connectionWithRequest:myURLRequest delegate:parentThread];
 //The delegate methods are setup in the rest of the class but they are never getting called...

 [pool drain];
}

EDIT*

The reason I need to run NSURLConnection on a separate thread is because I am downloading something in my iPhone app and the download cancels when the user locks the screen (it continues fine if the user simply presses the home button and the app goes into the background). I understand this is due to my running the connection asynchronously on the main thread and not a separate one.

I have also tried this code (NOT in a separate thread) when initiating the NSURLConnection:

  NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:myURLRequest delegate:self startImmediately:NO];
   [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   [connection start];
   [connection release];

But it I have the same problem with this regarding the download being cancelled on screen lock.

*UPDATE

To add to Thomas' answer below (Please note that James Webster's answer is also correct regarding the exiting of a thread) the Apple docs explain: "Suspended state - The app is in the background but is not executing code. The system moves apps to this state automatically and does not notify them before doing so. While suspended, an app remains in memory but does not execute any code."

Since when the screen is locked by the user the app is put into the background state and than right away into the suspended state, all execution is stopped killing any downloads and no warning that this is about to happen is given... there may be a notification which tells me that the user has locked the screen but I haven't found one yet.

I therefore pause (save certain information and cancel the NSURLConnection) all downloads when the app goes into the background and resume it with the HTTP Range header when it gets active again. This is a workaround which is ok but not ideal since the download is not occurring in the background which affects the user experience negatively... bummer.

Lampyrid answered 29/2, 2012 at 11:43 Comment(2)
the methods which you are using for NSURLConnection request are itself asynchronous so even if you do not detache new thread it will be multithreaded operation.Deepset
Edited question to better explain my issue.Lampyrid
F
1

Since your NSURLConnection is asynchronous, the end of your -startDownloading method is reached immediately, and the thread exits.

You should indeed schedule your connection on the main runloop (or use GCD).

The device lock is another issue. When the device is locked, your application is suspended to save battery life. You can probably ask for an extra amount of time when suspending in order to finish your download.

Favour answered 29/2, 2012 at 13:4 Comment(1)
Thanks. I updated my question to build on your answer. It appears that asking for more time is only for apps in the background and not those that are suspended.Lampyrid
E
0

I think your problem might be that the NSURLConnection has been deallocated as soon as you exit the startDownloading: message (or more accurately when your autorelease pool is drained)

However I think your methodology might be a bit uncouth anyway. NSURLConnection the way you are using it is asynchronous and will appear to be threaded anyway.

Try this and see if it works as you expect it to (i.e. your app doesn't pause while your connection is busy)

-(void)startConnectionWithUrlPath:(NSString*)URLpath {

    //initiates the download connection - setup
    NSURL *myURL = [[NSURL alloc] initWithString:URLpath];

    myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
    [myURL release];

    [NSURLConnection connectionWithRequest:myURLRequest delegate:self];
}
Eleen answered 29/2, 2012 at 11:51 Comment(3)
Edited question to better explain my issue.Lampyrid
Ok, your edit makes sense. Pay attention to the first bit of my answer then. It seems your NSURLConnection has been deallocated almost straight away.Eleen
This answer has been referenced as also being correct in my update of the question.Lampyrid

© 2022 - 2024 — McMap. All rights reserved.