Question

I just started using AFNetworking and so far it worked fine for just getting data from the web.

But now I have a list of files that need to be downloaded to the device

for(NSDictionary *issueDic in data)
{
    Issue *issue = [[Issue alloc] init];
    ...
    [self getOrDownloadCover:issue];
    ...
}

getOrDownloadCover:issue checks if a file already exists locally, if it does, it just saves that path, if it doesn't, it downloads the file from a given url

- (void)getOrDownloadCover:(Issue *)issue
{
    NSLog(@"issue.thumb: %@", issue.thumb);

    NSString *coverName = [issue.thumb lastPathComponent];

    NSLog(@"coverName: %@", coverName);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    __block NSString *filePath = [documentsDirectory stringByAppendingPathComponent:coverName];

    if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
    {
        // Cover already exists
        issue.thumb_location = filePath;

        NSLog(@"issue.thumb_location: %@", filePath);
    }
    else 
    {
        NSLog(@"load thumb");

        // Download the cover
        NSURL *url = [NSURL URLWithString:issue.thumb];
        AFHTTPClient *httpClient = [[[AFHTTPClient alloc] initWithBaseURL:url] autorelease];
        NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:issue.thumb parameters:nil];

        AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
        operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];

        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        issue.thumb_location = filePath;

        NSLog(@"issue.thumb_location: %@", filePath);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"FAILED");
    }];
        [operation start];
    }
}

getOrDownloadCover:issue can be called 20 times in a row, so I would need to put all my requests into a queue, and once the queue is completed, it should still be able to save the path (or just send out a notification, since I already know what the path is)

Any suggestions for this?

Was it helpful?

Solution

Add an NSOperationQueue to an object you can get the instance of at any point in your application, for example in your appDelegate. Then just add the AFHTTPRequestOperation to this queue like:

[[(AppDelegate *) [UIApplication sharedApplication].delegate operartionQueue] addOperation:operation];

Just handle the saving in the completion block, either call a methode from this block on the main thread or post a NSNotification.

To call the main thread use GCD :

dispatch_async(dispatch_get_main_queue(), ^{
    // Call any method from on the instance that created the operation here.
    [self updateGUI]; // example
});

OTHER TIPS

Not sure if this is helpful but...

Instead of using your own operationQueue you could use AFHTTPClient's operationQueue. Enqueue single operations with enqueueHTTPOperation or enqueue an array of operations with enqueueBatchOperations (I'm recalling these method names from memory, likely off a little).

As far as storing data specific to each operation, you could subclass AFHTTPRequestOperation and set properties for the path you'd like to store. Something like this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top