Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downloading files in serial order using NSURLConnection in iOS

I want to download 3 files in serial order. Two of them are txt files and one is .gz file. I am using NSURLConnection to download the above files.

I am very new to iOS Programming. I have seen in other question in SO and google that we can use serial dispatch queue to do some operation serially.

But I don't know how to do this with NSURLConnection. I tried below but did not work.

 dispatch_queue_t serialQueue = dispatch_queue_create("com.clc.PropQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
    [self downloadProp];
});
dispatch_async(serialQueue, ^{
    [self downloadDatabase];
});
dispatch_async(serialQueue, ^{
    [self downloadTxt];
});

Above code is not executing connectionDidFinishLoading of NSURLCOnnection. Anyone has Idea how to achieve this?

like image 765
Anjali Avatar asked Jul 13 '15 13:07

Anjali


2 Answers

NSURLSession provides a queue that will download each task in the order in which they are created.

NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionTask *task1 = [session dataTaskWithURL:[NSURL URLWithString:@"http://yahoo.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSLog(@"Complete 1");
}];
NSURLSessionTask *task2 = [session dataTaskWithURL:[NSURL URLWithString:@"http://msn.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSLog(@"Complete 2");
}];
NSURLSessionTask *task3 = [session dataTaskWithURL:[NSURL URLWithString:@"http://google.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSLog(@"Complete 3");
}];

// Regardless of which order the tasks are "resumed" (aka started) they will execute synchronously in the order added, above.
[task3 resume];
[task1 resume];
[task2 resume];

Update based on comments & chat:

To be more deterministic over the ordering & execution of tasks...

NSURLSession *session = [NSURLSession sharedSession];

__block NSURLSessionTask *task1 = nil;
__block NSURLSessionTask *task2 = nil;
__block NSURLSessionTask *task3 = nil;

task1 = [session dataTaskWithURL:urlToFirstFile completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // CHECK ERROR
    NSLog(@"First file completed downloading");
    [task2 resume];
}];
task2 = [session dataTaskWithURL:urlToSecondFile completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // CHECK ERROR
    NSLog(@"Second file completed downloading");
    [task3 resume];
}];
task3 = [session dataTaskWithURL:[NSURL URLWithString:@"http://google.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // CHECK ERROR
    NSLog(@"Third file completed downloading");
}];

[task1 resume];
like image 142
Steve Wilford Avatar answered Oct 19 '22 23:10

Steve Wilford


A simple recursive solution to ensure serial operation.

func serialisedRequests(session: URLSession, requests: [URLRequest], index: Int = 0) {

    if index >= requests.count {
        return
    }

    let task = session.dataTask(with: requests[index]) {
        data, response, error in
        serialisedRequests(session: session, requests: requests, index: index+1)
    }
    task.resume()
}
like image 30
naim Avatar answered Oct 19 '22 23:10

naim