Rajat Saini
Rajat Saini

Reputation: 557

How to force close NSURLConnection maunally?

I am using a NSURLConnection to make an http download. Depending upon the condition I may have to drop the connection after a specific download. Say, if my download is completed in 30 seconds then ok other wise download should be stopped after 30 seconds. Also I have to log these events. My problem is that, even after 30 seconds it keeps on downloading data and the events are logged only after download complete.

In simple words I want to force close the download and also want to disable all the delegate events that are fired by http connection. I do not want to set flags at multiple locations, that would complicate things further. Any Ideas?

Update: Complete scenario: I have set the timeoutInterval to 10 seconds in NSURLReqeust object. Now what happens if no data is received for 10 seconds the connection is automatically drops after 10 seconds works perfectly fine. But I have another feature in my software that requires to terminate the connection with download in not completed in given amount of time. I am using a separate NSTimer. All I can do is set a flag when NSTimer event is fired. Now in case the flag is set via NSTimer and data stops coming in, I have no connection delegate that would be fired for next 10 seconds. Now my problem is both the abort event and timeout events occurs at the same time.

Upvotes: 0

Views: 3479

Answers (2)

Mayur Birari
Mayur Birari

Reputation: 5835

Use NSURLRequest object to specify a timeout for evrey request you did for download by using this requestWithURL:cachePolicy:timeoutInterval: method.

Please check whether your NSURLConnection's delegate is set and responds to the connection:didFailWithError: method. A NSURLConnection calls either this method or connectionDidFinishLoading: upon connection completion.

Handle 'didFailWithError' method and check the reason for failer by using NSError object.

But if you get response from server and response time is slow, then used NSTimer. Create Helper class for downloading data so you can reuse the class for multiple downloads by creating several instances and set NSTimer in it, if download finish within 30 seconds invalidate timer else cancel downloading [self.connection cancel].

Please check following code:

- (void)_startReceive
    // Starts a connection to download the current URL.
{
    BOOL                success;
    NSURL *             url;
    NSURLRequest *      request;

        // Open a connection for the URL.
        request = [NSURLRequest requestWithURL:url];
        assert(request != nil);

        self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
        assert(self.connection != nil);

        // If we've been told to use an early timeout for get complete response within 30 sec, 
        // set that up now.
            self.earlyTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(_earlyTimeout:) userInfo:nil repeats:NO];
    }
}

- (void)_stopReceiveWithStatus:(NSString *)statusString
    // Shuts down the connection and displays the result (statusString == nil) 
    // or the error status (otherwise).
{
    if (self.earlyTimeoutTimer != nil) {
        [self.earlyTimeoutTimer invalidate];
        self.earlyTimeoutTimer = nil;
    }
    if (self.connection != nil) {
        [self.connection cancel];
        self.connection = nil;
    }
}

- (void)_earlyTimeout:(NSTimer *)timer
    // Called by a timer (if the download is not finish)
{
    [self _stopReceiveWithStatus:@"Early Timeout"];
}

- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
    // A delegate method called by the NSURLConnection when the request/response 
    // exchange is complete.  
{ }

- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
    // A delegate method called by the NSURLConnection as data arrives.  We just 
    // write the data to the file.
{ }

- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
    // A delegate method called by the NSURLConnection if the connection fails. 
{
    NSLog(@"didFailWithError %@", error);   
    // stop Receive With Status Connection failed
}

- (void)connectionDidFinishLoading:(NSURLConnection *)conn
    // A delegate method called by the NSURLConnection when the connection has been 
    // done successfully.  We shut down the connection with a nil status.
{
    NSLog(@"connectionDidFinishLoading");
    // If control reach here before timer invalidate then save the data and invalidate the timer
     if (self.earlyTimeoutTimer != nil) {
        [self.earlyTimeoutTimer invalidate];
        self.earlyTimeoutTimer = nil;
    }
}

Upvotes: 1

Nenad M
Nenad M

Reputation: 3055

Well, you "can" cancel a NSURLConnection by sending it a cancel event:

[connection cancel];

See Apple docs.

Prior to that just nil out the delegate and you should not be harassed by any delegate callbacks.

Upvotes: 2

Related Questions