I am passing a POST
message using NSURLSessionDataTask
in Objective-c.
The transfer task is non-blocking. I have to wait for the result so I use dispatch_semaphore_t
to wait.
Unfortunately, when the corresponding function is called, the task does not work, why is that? The code below is shown.
NSString *urlString = [NSString stringWithFormat:@"http://localhost/api/test"];
char json_string[20] = "reqtestmsg";
size_t jsonLength = strlen(json_string);
NSData *jsonBodyData = [NSData dataWithBytes:json_string length:jsonLength];
NSMutableURLRequest *request = [NSMutableURLRequest new];
request.HTTPMethod = @"POST";
// for alternative 1:
[request setURL:[NSURL URLWithString:urlString]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPBody:jsonBodyData];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
printf ("curl semaphore\n");
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block bool result = false;
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
NSHTTPURLResponse *asHTTPResponse = (NSHTTPURLResponse *) response;
NSLog(@"curl The response is: %@", asHTTPResponse);
if (asHTTPResponse.statusCode == 200) {
printf ("curl status 200 ok\n");
result = true;
}
dispatch_semaphore_signal(semaphore);
}];
[task resume];
printf ("curl wait!!!");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // ==> blocked , task does not work!!!!
printf ("curl wait!!! -1");
return result;
CodePudding user response:
You have specified your delegate queue to be the main queue. But you have blocked the main thread with dispatch_semaphore_wait
. This is a classical deadlock, waiting for code to run on a queue which is blocked.
You could specify nil
for your session’s delegate queue, and then you wouldn't deadlock. Or use [NSURLSession sharedSession]
.
I would also encourage you to consider eliminating the semaphores entirely. I understand the appeal of semaphores, but it is almost always the wrong solution. Apple removed synchronous networking API for a reason. The semaphore trick feels like an intuitive work-around, but it is inefficient, leads to substandard UX, and can even cause your app to be terminated by the watchdog process in certain situations.