详解iOS中多个网络请求的同步问题总结

场景描述:我们同时发出了a、b、c 3个网络请求,我们希望在a、b、c 3个网络请求都结束的时候获得一个通知。

常见解决方法:通过度娘目前找到两种做法;1、通过添加标识来判断请求是否全部结束 2、dispatch_group + 信号量

本篇文章demo

1、添加标识的解决方法

在遇到这个问题时首先想到了唐巧大大的猿题库团队开源的网络框架YTKNetwork,然后阅读源码发现YTKNetwork是通过添加标识来实现网络请求的批量请求处理;

话不多说直接上代码在YTKNetwork里负责进行网络批处理请求的是YTKBatchRequest类,下面看下它的使用示例:

YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[a, b, c, d]];先调用初始化方法把4个网络请求的实例塞进去,看下这个初始化方法

- (id)initWithRequestArray:(NSArray )requestArray {
  self = [super init];
  if (self) {
    _requestArray = [requestArray copy];
    _finishedCount = 0;
    for (YTKRequest req in _requestArray) {
      if (![req isKindOfClass:[YTKRequest class]]) {
        YTKLog(@"Error, request item must be YTKRequest instance.");
        return nil;
      }
    }
  }
  return self;
}

我们看到有一个_finishedCount的变量根据字面很好理解是用来记录请求完成的个数,然后我们全局搜下这个变量,发现只有在下面的这个方法中用到了这个变量

- (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];
  }
}

上述方法是网络请求结束的回调代理方法,完成后_finishedCount计数加1,然后和保存网络请求实例的数组元素个数进行比较如果相等说明所有的请求都已经完成,调用回调的代理方法及block请求结束。

然后YTKNetwork对于批量网络请求失败的处理是,只要一个失败就立即停止请求,调用失败回调:

- (void)requestFailed:(YTKRequest )request {
  [self toggleAccessoriesWillStopCallBack];
  // Stop
  for (YTKRequest req in _requestArray) {//遍历请求实例数组
    [req stop];//停止请求
  }
  // Callback  //回调
  if ([_delegate respondsToSelector:@selector(batchRequestFailed:)]) {
    [_delegate batchRequestFailed:self];
  }
  if (_failureCompletionBlock) {
    _failureCompletionBlock(self);
  }
  // Clear
  [self clearCompletionBlock];
  [self toggleAccessoriesDidStopCallBack];
  [[YTKBatchRequestAgent sharedInstance] removeBatchRequest:self];
}

总结:YTKNetwork的做法大致就是用一个变量记录完成请求的个数,然后在单个网络请求结束回调的时候判断当前完成的网络请求个数是否和总的网络请求个数相等,如果相等则说明请求结束。

2、dispatch_group + 信号量

参考文章采用的是group + 信号量,下面示例采用dispatch_group_enter、dispatch_group_leave实现详见 本篇文章demo

- (void)loadRequest1
{
  dispatch_group_t dispatchGroup = dispatch_group_create();
  dispatch_group_enter(dispatchGroup);
  [MALAFNManger getDataWithUrl:Url1 parameters:nil finish:^(RequestResult result) {
    NSLog(@"第一个请求完成");
    dispatch_group_leave(dispatchGroup);
  } des:@"第一个url"];
  dispatch_group_enter(dispatchGroup);
  [MALAFNManger getDataWithUrl:Url2 parameters:nil finish:^(RequestResult result) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
      sleep(10);//网络请求结束后回调是在主线程如果sleep放在外面会阻塞主线程
      NSLog(@"第二个请求完成");
      dispatch_group_leave(dispatchGroup);
    });
  } des:@"第二个url"];
  dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
    NSLog(@"请求完成");
  });
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS中多网络请求的线程安全详解

    前言 在iOS 网络编程有一种常见的场景是:我们需要并行处理二个请求并且在都成功后才能进行下一步处理.下面是部分常见的处理方式,但是在使用过程中也很容易出错: DispatchGroup:通过 GCD 机制将多个请求放到一个组内,然后通过 DispatchGroup.wait() 和 DispatchGroup.notify() 进行成功后的处理. OperationQueue:为每一个请求实例化一个 Operation 对象,然后将这些对象添加到 OperationQueue ,并且根据它们之

  • IOS 网络请求中设置cookie

    IOS 网络请求中设置cookie 1. ASIHTTPRequest ASIHTTPRequest 是一款极其强劲的 HTTP 访问开源项目.让简单的 API 完成复杂的功能,如:异步请求,队列请求,GZIP 压缩,缓存,断点续传,进度跟踪,上传文件,HTTP 认证. cookie的支持 如果 Cookie 存在的话,会把这些信息放在 NSHTTPCookieStorage 容器中共享,并供下次使用.你可以用 [ ASIHTTPRequest setSessionCookies:nil ] ;

  • 详解iOS中多个网络请求的同步问题总结

    场景描述:我们同时发出了a.b.c 3个网络请求,我们希望在a.b.c 3个网络请求都结束的时候获得一个通知. 常见解决方法:通过度娘目前找到两种做法:1.通过添加标识来判断请求是否全部结束 2.dispatch_group + 信号量 本篇文章demo 1.添加标识的解决方法 在遇到这个问题时首先想到了唐巧大大的猿题库团队开源的网络框架YTKNetwork,然后阅读源码发现YTKNetwork是通过添加标识来实现网络请求的批量请求处理: 话不多说直接上代码在YTKNetwork里负责进行网络批

  • 详解iOS AFNetworking取消正在进行的网络请求

    简介 项目开发时,开发人员经常会遇到一种情况,A控制器push进入B控制器,B控制器正在进行网络请求,请求未结束时,点击返回回到A控制器,现在问题出现了,B中网络请求还在执行,dealloc并未立即调用,为什么会发生这种情况?想在退出当前控制器时取消掉正在进行的请求,怎么做? 网络请求的封装 以AFNetworking为例,上我自己的网络请求封装主要代码: //单例模式 + (HttpManager *)sharedManager { static dispatch_once_t once; d

  • 详解IOS中文件路径判断是文件还是文件夹

    详解IOS中文件路径判断是文件还是文件夹 方法1 + (BOOL)isDirectory:(NSString *)filePath { BOOL isDirectory = NO; [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]; return isDirectory; } 方法2 + (BOOL)isDirectory:(NSString *)filePath { NSNum

  • 详解iOS中集成ijkplayer视频直播框架

    ijkplayer 是一款做视频直播的框架, 基于ffmpeg, 支持 Android 和 iOS, 网上也有很多集成说明, 但是个人觉得还是不够详细, 在这里详细的讲一下在 iOS 中如何集成ijkplayer, 即便以前从没有接触过, 按着下面做也可以集成成功! 一. 下载ijkplayer ijkplayer下载地址: http://xiazai.jb51.net/201612/yuanma/ijkplayer-master_jb51.rar 下载完成后解压, 解压后文件夹内部目录如下图:

  • 详解iOS中按钮点击事件处理方式

    写在前面 在iOS开发中,时常会用到按钮,通过按钮的点击来完成界面的跳转等功能.按钮事件的实现方式有多种,其中较为常用的是目标-动作对模式.但这种方式使得view与controller之间的耦合程度较高,不推荐使用: 另一种方式是代理方式,按钮的事件在view中绑定,controller作为view的代理实现代理方法. 目标-动作对实现方式 具体来说,假设我们有一个包含一个Button的veiw,view将Button放在头文件中,以便外部访问.然后controller将view作为自己的vie

  • 详解ios中的SQL数据库文件加密 (使用sqlcipher)

    今天本想写一片 GAE+goAgent+SwitchySharp 的指南的!但是突然翻出了前段时间写的关于iOS中的SQL数据库文件加密的代码,于是乎决定今天就先讲讲这个!- 那么goAgent将放在周末,后续的文章中除了文件加密,还有传输数据加密,感兴趣的童鞋 敬请留意. 言归正传,sql的文件加密,我们首先要用到一个库,它就是大名鼎鼎的Sqlcipher,  奉上连接:http://sqlcipher.NET,在ios里 我们需要看的文档是这一篇http://sqlcipher.Net/io

  • 详解iOS中Button按钮的状态和点击事件

    一.按钮的状态 1.UIControlStateNormal 1> 除开UIControlStateHighlighted.UIControlStateDisabled.UIControlStateSelected以外的其他情况,都是normal状态 2> 这种状态下的按钮[可以]接收点击事件 2.UIControlStateHighlighted 1> [当按住按钮不松开]或者[highlighted = YES]时就能达到这种状态 2> 这种状态下的按钮[可以]接收点击事件 3

  • 详解IOS中GCD的使用

    Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务.由于线程管理是作为系统的一部分来实现的,因此可统一管理,也可执行任务,这样就比以前的线程更有效率. 1. GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核.四核) GCD会自动管理线程的生命周期(创建线程.调度

  • 详解IOS中Tool Bar切换视图方法

    本文通过实例给大家详细讲解了IOS开发中Tool Bar切换视图方法以及原理解释,希望我们的整理对你有用,一起学习下. iOS中几种典型的多视图程序: (1)Tab Bar Application:程序的底部有一排按钮,轻触其中一个按钮,相应的视图被激活并显示出来: (2)Navigation-Based Application:其特点是使用navigation controller,而navigation controller使用navigation bar来控制多级视图: (3)Tool B

  • 详解iOS中position:fixed吸底时的滑动出现抖动的解决方案

    两种抖动 为什么抖动还会有两种? 其实是我碰到过两种抖动的场景,第一个场景是native的抖动,第二个场景是h5的抖动. native的抖动 前端开发人员会在app中打开webview,这个时候iOS中position:fixed吸底时的滑动出现抖动应该是native造成的抖动,整个viewport跟着动,所以可以在生成schema的时候将参数bounce_disable(可能不一定都有这个参数,就看有没有类似的参数进行控制)设置为1禁止native的弹性效果,然后加上h5的这个效果,-webk

随机推荐