NSURLConnection crashing app once timeout reached

Discussion in 'iOS Programming' started by robbieduncan, Aug 16, 2008.

  1. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #1
    I'm having an issue where NSURLConnection seems to be causing my application to crash. If I have code something like this then my application crashes after the timeout period, always and without exception.

    Code:
    // currentConnection and downloadedData are instance variables
    - (void) startDownload
    {
    	// URL is setup and valid 
    	NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
    	currentConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    	downloadedData = [[NSMutableData alloc] init];
    	[request release];
    	
    	// Start the download
    	[currentConnection start];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
    	// Append the received data to the current data
    	[downloadedData appendData:data];
    }
    
    - (void) downloadComplete
    {
    	[downloadedData release];
    	downloadedData = nil;
    	[currentConnection release];
    	currentConnection = nil;
    }
    
    // parseData does exist and parses the downloaded HTML to extract data.  It deals with saving the parsed data to the data model
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    	[self parseData];
    	[self downloadComplete];
    }
    
    As far as I can see this is valid code. But 30 seconds after the start call the app is crashed every single time. I think what is happening is that I am releasing the connection object (currentConnection) far quicker than the timeout as the download completes within that time. The timeout handler that NSURLConnection has setup then fires and causes the exception.

    So has anyone else seen this? If so did you come up with a good solution? The only solution I can think of is to hold on to the connection object for at least as long as timeout and then release it afterwards...
     
  2. robbieduncan thread starter Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Ok so not releasing the connection or holding on to it for at least twice as long as the timeout makes no difference.

    The signal is "EXC_BAD_ACCESS". The callstack that seems to be causing this is:

    #0 0x9691f63e in timeoutConnection
    #1 0x96d2fb45 in CFRunLoopRunSpecific
    #2 0x96d2fcf8 in CFRunLoopRunInMode
    #3 0x91f31460 in +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]
    #4 0x91ecdf1d in -[NSThread main]
    #5 0x91ecdac4 in __NSThread__main__
    #6 0x91d946f5 in _pthread_start
    #7 0x91d945b2 in thread_start

    Making the timout longer or shorter simply delays or speeds up the crash. Any ideas?

    Edit to add: even worse I can't reproduce this on an actual iPhone!
    Edit again: spoke too soon, had the wrong code loaded on the phone. Seems to hang the whole device!
     
  3. Sbrocket macrumors 65816

    Sbrocket

    Joined:
    Jun 3, 2007
    Location:
    /dev/null
    #3
    You need to implement - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error.
     
  4. robbieduncan thread starter Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    Thanks for the suggestion, but that is implemented as

    Code:
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
    	// Something went wrong!
    	[self downloadComplete];
    }
    
    I know that there is not an error: parseData is running and the UI updates. The only way parseData can get called is if connectionDidFinishLoading: gets called. So there is no failure of the connection. The connection successfully downloads the web page I want and then after whatever I set the timeout to in the NSURLRequest it kills the application.
     
  5. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #5
    Don't call start, because when you use initWithRequest:delegate:, the download begins immediately. If you don't want this, use initWithRequest:delegate:startImmediately:
     
  6. robbieduncan thread starter Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #6
    Perfect. That appears to have fixed the timeout issue, a different internal connection issue I was seeing and an occasional issue I was having with the data doubling up.

    I owe you a pint...
     

Share This Page