iosobjective-cafnetworking-2nsoperationqueueafhttprequestoperation

How to download multiple files from multiple url by NSOperationQueue


I'm struggling to implement download mechanism for multiple files using AFNetworking. I want to download zip file one after another from multiple url with progression message. I tried like following code, but getting error as -

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSOperationQueue addOperation:]: operation is already enqueued on a queue'

Here is my code portion :

- (void) downloadCarContents:(NSArray *)urlArray forContent:(NSArray *)contentPaths {

    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

    for (int i=0; i< urlArray.count; i++) {

        NSString *destinationPath = [self.documentDirectory getDownloadContentPath:contentPaths[i]];

        NSLog(@"Dest : %@", destinationPath);

        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        AFHTTPRequestOperation *operation = [manager GET:urlArray[i]
                                              parameters:nil
                                                 success:^(AFHTTPRequestOperation *operation, id responseObject) {

                                                 } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

                                                     NSLog(@"Error : %ld", (long)error.code);
                                                 }];

        operation.outputStream = [NSOutputStream outputStreamToFileAtPath:destinationPath append:NO];

        [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
            float percentage = (float) (totalBytesRead * 100) / totalBytesExpectedToRead;
            [self.delegate downloadProgression:percentage];
        }];

        [operationQueue addOperation:operation];
    }
}

Please help.


Solution

  • When you call GET, it's already added to the operationQueue of the AFHTTPRequestionOperationManager. So don't add it to a queue again.

    Also, you should instantiate the AFHTTPRequestOperationManager once, before the loop, not repeated within the loop.


    There are other problems with this code, but rather than trying to address all of these issues, I'd suggest you transition to AFHTTPSessionManager, which uses NSURLSession. The old AFHTTPRequestOperationManager was NSURLConnection-based, but NSURLConnection is now deprecated. And, in fact, AFNetworking 3.0 has retired AFHTTPRequestOperationManager entirely.

    So, the AFHTTPSessionManager rendition might look like:

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    for (NSInteger i = 0; i < urlArray.count; i++) {
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlArray[i]]];
        NSURLSessionTask *task = [manager downloadTaskWithRequest:request progress:^(NSProgress *downloadProgress) {
            [self.delegate downloadProgression:downloadProgress.fractionCompleted * 100.0];
        } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
            return [NSURL fileURLWithPath:[self.documentDirectory getDownloadContentPath:contentPaths[i]]];
        } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
            NSLog(@"File downloaded to: %@", filePath);
            NSLog(@"Error: %@" error.localizedDescription);
        }];
        [task resume];
    }