You've taken an inherently asynchronous method, dataTaskWithRequest, and have made it synchronous (i.e. it blocks the thread from which it was called). Get rid of all of that semaphore stuff. It's a really bad pattern, anyway.
I assume you did that because you wanted to return data from a network call. You shouldn't do that. You should use a completion handler pattern, e.g.
For example, let's imagine your method currently looks like:
- (id)performRequest:(NSURLRequest *)request {
__block id header;
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
} else {
header = responseObject;
}
dispatch_semaphore_signal(semaphore);
}];
[dataTask resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return header;
}
You should change it to a void return type, and add a completionHandler parameter:
- (void)performRequest:(NSURLRequest *)request completionHandler:(void (^)(id _Nullable responseObject, NSError * _Nullable error))completionHandler {
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
completionHandler(nil, error);
} else {
completionHandler(responseObject, nil);
}
}];
[dataTask resume];
}
And you'd call it like so:
[self performRequest:request completionHandler:^(id responseObject, NSError *error) {
// use responseObject and error here
}];
// but not here