美文网首页开发杂谈iOS网络技术iOS酷玩技术分享
网络封装处理(一)使用GCD同步网络请求

网络封装处理(一)使用GCD同步网络请求

作者: 冲破茧缚 | 来源:发表于2016-11-27 21:43 被阅读300次

    现实开发中,经常会遇到这样的需求,一个页面需要批量发送几个网络请求,并且对这几个网络请求进行统一处理。这种情况直接用AFNetworking实现不了,需要对其进行进一步的封装。

    实现思路:

    1. 把要批量发送的请求放入一个数组,遍历数组,依次发送请求,定义一个已完成的请求数量计数器,每个请求完成是对该计数器加一,然后判断计数器是否和请求数组的请求个数一致,如果一致则代表请求完成。
    2. 跟第一个方法相似,只是判断请求完成的方法不同,使用GCD的信号量dispatch_semaphore,配合dispatch_group来实现。

    下面来具体的讲述以上两种方法:

    1. 通过请求计数器来判断 :

    猿题库开源的网络库框架YTKNetwork里面处理批量请求就是用这种方法,它有一个类YTKBatchReques,就是用来实现批量请求的,它实现了一个方法requestFinished,该方法对已完成的请求数量_finishedCount进行自增,然后判断其是否与请求数组_requestArray中的请求个数相等,若相等则执行一系列批量请求完成的操作。

    - (void)requestFinished:(YTKRequest *)request {
        _finishedCount++;
        if (_finishedCount == _requestArray.count) {
            [self toggleAccessoriesWillStopCallBack];
            if ([_delegate respondsToSelector:@selector(batchRequestFinished:)]) {
                [_delegate batchRequestFinished:self];
            }
            if (_successCompletionBlock) {
                _successCompletionBlock(self);
            }
            [self clearCompletionBlock];
            [self toggleAccessoriesDidStopCallBack];
            [[YTKBatchRequestAgent sharedInstance] removeBatchRequest:self];
        }
    }
    

    2. GCD信号量dispatch_semaphore:

    首先了解下信号量的几个方法
     1.dispatch_semaphore_create(long value);
       创建信号量,传入的value值要大于等于0,返回一个信号量
     2.dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
       如果信号量的value值大于0,则会往下执行并将value的值减1,否则,阻碍当前线程并等待timeout后再往下执行。如果等待的期间desema的值被dispatch_semaphore_signal函数加1了,且该函数所处线程获得了信号量,那么就继续向下执行并将信号量减1。如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程会自动往下执行。
     3.dispatch_semaphore_signal(dispatch_semaphore_t dsema);
       返回值为long类型,当返回值为0时表示当前并没有线程等待其处理的信号量,其处理的信号量的值加1即可。当返回值不为0时,表示其当前有(一个或多个)线程等待其处理的信号量,并且该函数唤醒了一个等待的线程(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒)。
    
    实现过程:
    • 创建一个任务组dispatch_group
     dispatch_group_t group = dispatch_group_create();
    
    • 将每个请求包装成一个任务异步提交到任务组里,每个任务在一开始创建一个信号量,value值为0,任务最后在网络请求完成前进行信号量的等待,如果网络请求完成,则调用 'dispatch_semaphore_signal(semaphore);'对信号值加1,则线程不再进行信号量的等待,继续往下执行。当所有请求都完成时,会在dispatch_group_notify里的回调进行相应的处理。
     dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        // 创建信号量
         dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
         NSURLSessionDataTask *task = [manager GET:service.url parameters:service.parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            // 如果请求成功,增加信号量值
            dispatch_semaphore_signal(semaphore);
             // 成功回调 主线程执行
             dispatch_async(dispatch_get_main_queue(), ^{
                   !service.requestComplete?:service.requestComplete(responseObject,nil);
               });
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                 // 如果请求失败,增加信号量值
                 dispatch_semaphore_signal(semaphore);
            }];
                        
         // 在网络请求任务成功之前,信号量等待中
         dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
     });
    
      dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 所有请求完成时回调
      });
    
    参考链接

    http://www.cnblogs.com/snailHL/p/3906112.html
    https://github.com/yuantiku/YTKNetwork

    相关文章

      网友评论

      • luzsyn::+1:🏻:+1:🏻:+1:🏻一直被多个网络请求困扰着

      本文标题:网络封装处理(一)使用GCD同步网络请求

      本文链接:https://www.haomeiwen.com/subject/ejcnpttx.html