iOS 多个异步网络请求全部返回后再执行具体逻辑的方法

先看一段错误的方法:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSURLSession *session = [NSURLSession sharedSession];

    dispatch_queue_t dispatchQueue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){

        NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"got data from internet1");
        }];
        [task resume];

    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"got data from internet2");
        }];
        [task resume];
    });

    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    });
}

看看log的输出

2016-07-13 17:42:55.170 aaaa[4797:295528] end
2016-07-13 17:42:55.322 aaaa[4797:295574] got data from internet2
2016-07-13 17:42:55.375 aaaa[4797:295574] got data from internet1

完全没有达到效果。这是因为这里的网络请求是个异步的方法,没有等待具体的数据返回,放入的dispatch queue的 block就执行完毕了。所以没收到2个网络数据,就提前调用了dispatch_group_notify指定的结束方法。

再看正确的方法:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSURLSession *session = [NSURLSession sharedSession];

    dispatch_queue_t dispatchQueue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    // dispatch_group_async(dispatchGroup, dispatchQueue, ^(){

    dispatch_group_enter(dispatchGroup);

    NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"got data from internet1");

        dispatch_group_leave(dispatchGroup);
    }];
    [task resume];

    //  });
    //  dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
    dispatch_group_enter(dispatchGroup);

    NSURLSessionDataTask *task2 = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"got data from internet2");

        dispatch_group_leave(dispatchGroup);
    }];
    [task2 resume];
    // });

    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    });
}

看正确是输出结果:

2016-07-13 17:46:10.282 aaaa[4847:300370] got data from internet1
2016-07-13 17:46:10.501 aaaa[4847:300370] got data from internet2
2016-07-13 17:46:10.502 aaaa[4847:300341] end

我们看看关于dispatch_group_enter 的具体说明

Calling this function increments the current count of outstanding tasks in the group. Using this function (with dispatch_group_leave) allows your application to properly manage the task reference count if it explicitly adds and removes tasks from the group by a means other than using the dispatch_group_async function. A call to this function must be balanced with a call to dispatch_group_leave. You can use this function to associate a block with more than one group at the same time.

简单的说,就是dispatch_group_enter会对group的内部计数加一,dispatch_group_leave会对group的内部计数减一,就类似以前的retain和release方法。说白了也是维护了一个计数器,只不过系统将这个计数器封装了起来,不用我们自己实现了,代码看起来更简洁,高大上了。

时间: 2024-10-11 11:55:56

iOS 多个异步网络请求全部返回后再执行具体逻辑的方法的相关文章

iOS NSURLConnection和异步网络请求

在日常应用中,我们往往使用AFNetworking等第三方库来实现网络请求部分.这篇文章会简要地介绍一下如何使用NSURLConnection来进行异步的网络请求. 我们先看一个小demo - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *urlStr = @"http://www.baidu.c

iOS开发——post异步网络请求封装

IOS中有许多网络请求的函数,同步的,异步的,通过delegate异步回调的. 在做一个项目的时候,上网看了很多别人的例子,发现都没有一个简单的,方便的异步请求的封装例子.我这里要给出的封装代码,是异步的,post的请求方式.通过ios的原生函数简单封装.通过这个封装可以方便的访问http服务器,获取数据,也可以容易的异步加载网络图片. 首先新建一个httpHelper类,在这个类里进行封装,封装的函数名称就叫做post,参数有请求的地址url,请求的参数params,返回数据后回调的函数blo

多个网络请求成功返回再执行另外任务的思路分析(iOS)

前言 今天我们来讨论一个经常出现的需求场景,也是一个老话题.在开发中我们往往会遇到需要进行多个网络请求,并且需要多个网络请求成功返回后再做其他事的场景.比如同一个界面显示的内容需要用到两个网络接口,而需求又希望成功返回两个接口的数据再进行页面展示:又比如喜欢挖坑的后台同学就只提供了返回一条数据的接口,但需求却希望我们在一个界面同时显示几条数据的情况. 正题 我们不讨论什么执行完一个请求再执行一个这种串行的低效率方法,以下分析都是在异步的基础上进行的.废话少说,直奔正题!先上个网络请求的模拟代码.

iOS 开发 把握AFNet网络请求完成的正确时机

前言 对于iOS开发中的网络请求模块,AFNet的使用应该是最熟悉不过了,但你是否把握了网络请求正确的完成时机?本篇文章涉及线程同步.线程依赖.线程组等专用名词的含义,若对上述名词认识模糊,可先进行查阅理解后阅读本文.如果你也纠结于文中所述问题,可进行阅读希望对你有所帮助.大神无视勿喷. 在真实开发中,我们通常会遇到如下问题: 一.某界面存在多个请求,希望所有请求均结束才进行某操作. 对于这一问题的解决方案很容易想到通过线程组进行实现.代码如下: 1 2 3 4 5 6 7 8 9 10 11

iOS开发中的网络请求

今天来说说关于iOS开发过程中的网络请求. 关于网络请求的重要性我想不用多说了吧.对于移动客户端来说,网络的重要性不言而喻.常见的网络请求有同步GET, 同步POST, 异步GET, 异步POST.今天来看一下四种网络请求的实现方式. 一.同步GET // 1.将网址初始化成一个OC字符串对象 NSString *urlStr = [NSString stringWithFormat:@"%@?query=%@&region=%@&output=json&ak=6E823

Android中的异步网络请求

本篇文章我们来一起写一个最基本的Android异步网络请求框架,借此来了解下Android中网络请求的相关姿势.由于个人水平有限,文中难免存在疏忽和谬误,希望大家可以指出,谢谢大家:) 1. 同步网络请求 以HTTP的GET请求为例,我们来介绍一下Android中一个基本的同步请求框架的实现.直接贴代码: public class HttpUtils { public static byte[] get(String urlString) { HttpURLConnection urlConne

Github 上Top1的Android 异步网络请求框架

今天给大家分享一个github上Top1的Android异步网络请求框架的使用方法,我给大家分享一个它的基本用法. 先来一个简单的get请求 AsyncHttpClient client = new AsyncHttpClient(); client.get("http://www.google.com", new AsyncHttpResponseHandler() { @Override public void onStart() { // called before reques

iOS AFNetWorking中block执行完后再执行其它操作

需求:同时进行两次网络请求,网络请求是异步的,在网络请求成功后进行其它的操作.两个网络请求是这样,一个网络请求中block执行完之后,再进行其它操作,也是一样的原理,只是这时候不需要线程组了,只需要信号量.当然也适用于所有的block. 接下来就说下,在两次异步请求之后要做的操作. 利用线程组和信号量来完成,看代码 - (void)getData { NSString *appIdKey = @"8781e4ef1c73ff20a180d3d7a42a8c04"; NSString*

【jquery】ajax 请求成功后新开窗口被拦截解决方法

问题: 前面开发项目时碰到一个问题,ajax 异步请求成功后需要新开窗口打开 url,使用的是 window.open() 方法,但是很可惜被浏览器给拦截了,怎么解决这个问题呢? 分析: 浏览器之所以拦截新开窗口是因为该操作并不是用户主动触发的,所以它认为这是不安全的就拦截了(不过如果是 _self 的话就不会有这个限制),即使 ajax 回调函数中模拟执行 click 或者 submit 等用户行为(trigger('click')),浏览器也会认为不是由用户主动触发的,因此不能被安全执行,所