To expand / update @Kasik's answer. You can create a category in AFNetworking in the same way using semaphores:
@implementation AFHTTPSessionManager (AFNetworking) - (id)sendSynchronousRequestWithBaseURLAsString:(NSString * _Nonnull)baseURL pathToData:(NSString * _Nonnull)path parameters:(NSDictionary * _Nullable)params { __block id result = nil; dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); AFHTTPSessionManager *session = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:baseURL]]; [session GET:path parameters:params progress:nil success:^(NSURLSessionDataTask *task, id responseObject) { result = responseObject; dispatch_semaphore_signal(semaphore); } failure:^(NSURLSessionDataTask *task, NSError *error) { dispatch_semaphore_signal(semaphore); }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return result; } @end
If you call the synchronization block inside the completion block of another AFNetwork request, be sure to change the completionQueue property. If you do not change it, the synchronous block will call the main queue upon completion, already in the main queue, and your application will crash.
+ (void)someRequest:(void (^)(id response))completion { AFHTTPSessionManager *session = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:@""] sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; dispatch_queue_t queue = dispatch_queue_create("name", 0); session.completionQueue = queue; [session GET:@"path/to/resource" parameters:nil progress:nil success:^(NSURLSessionDataTask *task, id responseObject) { NSDictionary *data = [session sendSynchronousRequestWithBaseURLAsString:@"" pathToData:@"" parameters:nil ]; dispatch_async(dispatch_get_main_queue(), ^{ completion (myDict); }); } failure:^(NSURLSessionDataTask *task, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ completion (error); }); }];
Mark Bourke Mar 15 '16 at 20:36 2016-03-15 20:36
source share