AFNetworking 2.x 同步请求
使用waitUntilFinished阻塞当前线程,直到该NSOperation结束
- (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等等的同步
- (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方法为同步
- (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 同步请求
- (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
根据这样的原理,我们便可以快速的将异步请求转换为同步任务:
- (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异步请求使用信号量
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");
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");