最新消息:iOS编程开发交流群(6906921) ,Mac.Cocoa开发交流群(7758675) 欢迎iOS/macOS开发编程爱好及学习者加入!

iOS开发之NSURLSession与AFNetworking 2.x/3.x实现同步请求

iOS 天狐 14125浏览 1评论

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");

 

转载请注明:天狐博客 » iOS开发之NSURLSession与AFNetworking 2.x/3.x实现同步请求

微信 OR 支付宝 扫描二维码
为天狐 打赏
非常感谢你的支持,哥会继续努力!
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. dispatch_semaphore_wait一直在等待,AFHTTPSessionManager 请求完成,主队列回调肯定不会走啊
    爆seed8年前 (2017-06-30)回复