Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronous NSURLSessionDataTask using Objective-C

I'm try to do synchronous NSURLSessionDataTask with the below code but unable to proceed.

__block NSData *rData = nil;
  __block BOOL taskDone = NO;
 __block NSData *rError = nil;


    NSURL *url = [NSURL URLWithString:dataURL];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:1 timeoutInterval:30];
   
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:nil delegateQueue:nil];
    NSURLSessionDataTask *taskData = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        rData = [NSData dataWithData:data];
        rError = [error copy];
        
        taskDone = YES;
    }];
    
    [taskData resume];

    while (taskDone == NO) {
        if (_close == YES) {
            [taskData cancel];
            return nil;
        }
        usleep(20000);
    }

I need to synchronous call so that I can remove the while loop which is not needed. Below is my code with synchronous call using semaphore

 dispatch_semaphore_t sem;
   __block NSData *rData = nil;
   __block BOOL taskDone = NO;
  __block NSData *rError = nil;


    NSURL *url = [NSURL URLWithString:dataURL];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:1 timeoutInterval:30];
   
    // creating semaphore
    sem = dispatch_semaphore_create(0);
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:nil delegateQueue:nil];
    NSURLSessionDataTask *taskData = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        rData = [NSData dataWithData:data];
        rError = [error copy];
        
        taskDone = YES;

        //call semaphore
        dispatch_semaphore_signal(sem); 
    }];
    
    [taskData resume];
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    dispatch_release(sem);


   // THIS part not sure...  how can we accommodate this below code
    while (taskDone == NO) {
        if (_close == YES) {
            [taskData cancel];
            return nil;
        }
        usleep(20000);
    }

above code could be correct ?

like image 360
sia Avatar asked Jul 27 '26 15:07

sia


1 Answers

I understand that what you want to do is wait for the DataTask to be completed before continue with you code, the best way is to put your request in a function with a completionHandler.

First create a function that will return a NSURLSessionDataTask with a completion handler:

-(NSURLSessionDataTask*)startSessionDataTaskWithCompletionHandler:(void (^)(NSData *myData))completionBlock {
    //Set your request
    NSString *dataURL = @"www.yoururl.com";
    NSURL *url = [NSURL URLWithString:dataURL];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:1 timeoutInterval:30];

    // I recommend to use sharedSession because is a simple request, so its not needed a specific session configuration.
    NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest: request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            if (completionBlock){
                completionBlock(data);
                return;
                //When you call this function, the completionBlock will use this data
            }
        } else {
            //Error handle
            return;
        }
    }];
    [dataTask resume];
    return dataTask;
}

Then you can call this function from anywhere:

NSURLSessionTask *task = [self startSessionDataTaskWithCompletionHandler:^(NSData *myData) {
    // put whatever code you want to perform when the asynchronous data task finish, for example:
    rData = [NSData dataWithData:myData];
}];
if (!task) {
    // handle failure to create task any way you want
}
like image 144
L33MUR Avatar answered Jul 29 '26 07:07

L33MUR