AFNetworking 2.x 同步请求
使用waitUntilFinished阻塞当前线程,直到该NSOperation结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- (NSDictionary *)sendSynchRequest:(NSString *)URLString parameters:(NSDictionary*)parameters { AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer]; NSMutableURLRequest *request = [requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializer]; [operation setResponseSerializer:responseSerializer]; [operation start]; [operation waitUntilFinished]; id responseObject = operation.responseObject; NSLog(@"server respone JSON\n:%@",[responseObject JSONStringValue]); return responseObject; } |
AFNetworking 3.x 同步请求
使用GCD信号量实现AFNetworking常用数据请求POST,GET等等的同步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
- (void)viewDidLoad { [super viewDidLoad]; NSError *error = nil; id respone = [self POST:@"http://api.skyfox.org/project/afndemo/newsList.do" parameters:nil error:&error]; NSLog(@"respone:%@",respone); } - (id)POST:(NSString *)URLString parameters:(NSDictionary *)parameters error:(NSError **)returnError { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block id data = nil; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { data = responseObject; dispatch_semaphore_signal(semaphore); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { if (returnError) { *returnError = error; } dispatch_semaphore_signal(semaphore); }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return data; } |
使用GCD信号量 更改dataTaskWithRequest方法为同步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
- (id)sendSynchronousDataTaskWithRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)returnResponse error:(NSError **)returnError { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block NSData *data = nil; [[[AFHTTPSessionManager manager] dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { data = responseObject; if (returnResponse) { *returnResponse = response; } if (returnError) { *returnError = error; } dispatch_semaphore_signal(semaphore); }]resume]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return data; } |
NSURLSession 同步请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
- (NSData *)sendSynchronousDataTaskWithRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)returnResponse error:(NSError **)returnError { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block NSData *data = nil; [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *taskData, NSURLResponse *taskResponse, NSError *taskError) { data = taskData; if (returnResponse) { *returnResponse = taskResponse; } if (returnError) { *returnError = taskError; } dispatch_semaphore_signal(semaphore); }] resume]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return data; } |
GCD信号量
信号量是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。
在GCD中有三个函数是semaphore的操作,分别是:
- dispatch_semaphore_create 创建一个semaphore, 有一个整形的参数,我们可以理解为信号的总量
- dispatch_semaphore_signal 发送一个信号,会让信号总量加1
- dispatch_semaphore_wait 等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1
根据这样的原理,我们便可以快速的将异步请求转换为同步任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
- (void)viewDidLoad { [super viewDidLoad]; NSDictionary *dic = [self getData:@{@"t":@"123"}]; NSLog(@"dic%@",dic); } //已知的异步方法 - (void)getData:(id)data completion:(void (^)(NSDictionary *dict))completion{ //模拟耗时操作 sleep(5); NSDictionary *dict = @{@"return":@"done"}; completion(dict); } //修改后的同步方法 -(NSDictionary*)getData:(id)data { __block NSDictionary *returnDic = nil; dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [self getData:data completion:^(NSDictionary *dict) { NSLog(@"semaphore +1"); dispatch_semaphore_signal(semaphore); //+1 semaphore returnDic = dict; }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"main thread"); return returnDic; } |
GCD异步请求使用信号量
1 2 3 4 5 6 7 8 9 |
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"start"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"semaphore +1"); dispatch_semaphore_signal(semaphore); //+1 semaphore }); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"main thread"); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
dispatch_semaphore_t semaphore1 = dispatch_semaphore_create(0); dispatch_semaphore_t semaphore2 = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"thread 2"); sleep(2); dispatch_semaphore_signal(semaphore2); }); dispatch_semaphore_wait(semaphore2, DISPATCH_TIME_FOREVER); NSLog(@"thread 1"); sleep(2); dispatch_semaphore_signal(semaphore1); }); dispatch_semaphore_wait(semaphore1, DISPATCH_TIME_FOREVER); NSLog(@"main thread"); |