Reputation: 402
As
NSURLConnection sendSynchronousRequest:returningResponse:error:&connectionError
is set deprecated I will have to replace an Importer I wrote a long time ago.
The Importer does the following:
I implemented this with a background-operation where I use methods for each API which called recursively if there are mulitple pages for the request.
But as NSURLSession does not support synchronous request I currently only see the option to have lot of overhead (e.g. iVars) control what's called in the completion block (e.g. next Page or start to query API-B).
So, what would be an elegant solution to bring this to NSURLSession.
NB: Just to make sure, my previous solution does not block the main thread at all. But back then it was the easiest way to control the merge of two sources.
Upvotes: 2
Views: 4007
Reputation: 1352
This's an example in AFNetworking
, it shows how to wait an asynchronous task.
- (NSArray *)tasksForKeyPath:(NSString *)keyPath {
__block NSArray *tasks = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
tasks = dataTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) {
tasks = uploadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) {
tasks = downloadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) {
tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return tasks;
}
Upvotes: 2
Reputation: 1223
This answer is not supposed to be best practice. It was just practical for me.
Faced with the situation when a bunch of synchronous requests is executed in background and the order of execution matters I've ended up using the following:
SyncRequestSender.h
#import <Foundation/Foundation.h>
@interface SyncRequestSender : NSObject
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response
error:(NSError **)error;
@end
SyncRequestSender.m
#import "SyncRequestSender.h"
@implementation SyncRequestSender
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response
error:(NSError **)error
{
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
NSError __block *err = NULL;
NSData __block *data;
NSURLResponse __block *resp;
[[[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData* _data, NSURLResponse* _response, NSError* _error) {
resp = _response;
err = _error;
data = _data;
dispatch_group_leave(group);
}] resume];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if (response)
{
*response = resp;
}
if (error)
{
*error = err;
}
return data;
}
@end
Upvotes: 9