Take the 2-minute tour ×

I know this question was asked many times on SO, but I didn't manage to make it work in my project...

So, I want to subclass NSOperation and make it download a file using NSURLConnection. What is the right way to do it? here is my code which doesn't work: First, I'm adding all my operations in a loop:

DownloadFileOperation *operation;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
operation = [[DownloadFileOperation alloc] init];
operation.urlString = pdfUrlString;
[queue addOperation:operation];
operation = nil; }

And here is my subclass:

@interface DownloadHandbookOperation : NSOperation <NSURLConnectionDelegate>


@property (strong, nonatomic) NSString *urlString;


@implementation DownloadHandbookOperation
    NSString *filePath;
    NSFileHandle *file;
    NSURLConnection * connection;

- (void)start
    if (![NSThread isMainThread])

    NSURL *url = [[NSURL alloc] initWithString:[self.urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];

    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    [req addValue:@"Basic ***=" forHTTPHeaderField:@"Authorization"];
    connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];


- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
    NSString *filename = [[conn.originalRequest.URL absoluteString] lastPathComponent];
    filename = [filename stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:filename];
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];

    file = [NSFileHandle fileHandleForUpdatingAtPath:filePath] ;
    if (file)
        [file seekToEndOfFile];
        [self finish];

- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
    if (file) {
        [file seekToEndOfFile];
    [file writeData:data];

- (void)connectionDidFinishLoading:(NSURLConnection *)conn
    [file closeFile];
    [self finish];

- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
    connection = nil;

    [self finish];

- (void)cancel
    [super cancel];
    [connection cancel];

- (void)finish


What am I doing wrong?

share|improve this question
I think NSURLConnection has to be called from the main thread, it doesn't do anything if called from a background thread... Also even though it's called from the main thread it still actually does the network stuff in the background, and then calls your delegate functions from the main thread again... –  jjv360 Feb 25 '13 at 14:27
Right, so how can I make my NSOperation be executed on main thread then? –  Oleg Feb 25 '13 at 14:38
Try [[NSOperationQueue mainQueue] addOperation:operation]... –  jjv360 Feb 25 '13 at 14:40
It worked, but now I can't control my queue and cancel/track operations? –  Oleg Feb 25 '13 at 14:54
Yes. NSURLConnection runs on a background thread, another way to describe this is to say that NSURLConnection "is concurrent". How do you stop NSOperation running "background in background"? You tell it that your operation is already concurrent by returning isConcurrent = YES. This tells NSOperation not to create a separate background thread for this operation. Your operation will handle this. Once you take control you also have to say when you are finished through isFinished and isExecuting. I'll try to dig out a good example and add it to my answer. –  Rory O'Bryan Feb 25 '13 at 19:49
show 4 more comments

1 Answer

up vote 5 down vote accepted

You need to properly configure your operation to execute as a "concurrent operation"

Concurrency Programming Guide: Configuring Operations for Concurrent Execution

You need to return isConcurrent = YES and properly manage the other state flags, isExecuting and isFinished in a KVO compliant manner.

To illustrate the general idea here is a post from the engineers at Pulse that describes their solution with some easy to follow demo code you can download and review.

Pulse Engineering Blog: Concurrent Downloads using NSOperationQueues

This code also handles the requirement that NSURLConnection is started on a thread with an active runloop by ensuring that it starts it on the main thread.

share|improve this answer
Thank you for the link, it helped! –  Oleg Feb 26 '13 at 9:03
Thanks for answer :-) –  Arkan Sep 17 '13 at 15:04
add comment

Your Answer


