美文网首页iOS开发iOS开发iOS开发精华
iOS多个网络请求完成后执行下一步

iOS多个网络请求完成后执行下一步

作者: _清墨 | 来源:发表于2017-12-05 08:11 被阅读1579次

    在开发中,我们很容易遇到这样的需求,需要我们同时做多个网络请求,所有网络请求都完成后才能进行下一步的操作。如下载多个图片,下载完了才能展示。

    今天我们就来研究一下这个问题的解决方案。

    1.首先,我们创建一个项目,然后做一般性的做法,不做任何处理去连续请求一个接口10次:

    先在viewDidLoad中创建第一种情况.

    //1.无处理
        UIButton *Btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
        Btn1.frame = CGRectMake(100, 100, 100, 40);
        Btn1.backgroundColor = [UIColor grayColor];
        [Btn1 setTitle:@"noConduct" forState:UIControlStateNormal];
        [Btn1 addTarget:self action:@selector(Btn1) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:Btn1];
    

    实现第一种情况的方法

    //1.noConduct
    -(void)Btn1{
        NSString *str = @"http://www.jianshu.com/p/6930f335adba";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];
        
        for (int i=0; i<10; i++) {
            NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                
                NSLog(@"%d---%d",i,i);
                
            }];
            
            [task resume];
        }
        
        NSLog(@"end");
    }
    

    运行,看看我们的控制台输出:

    2017-12-04 17:10:10.503 DownImage[3289:261033] end
    2017-12-04 17:10:10.676 DownImage[3289:261080] 0---0
    2017-12-04 17:10:10.704 DownImage[3289:261080] 1---1
    2017-12-04 17:10:10.754 DownImage[3289:261096] 4---4
    2017-12-04 17:10:10.760 DownImage[3289:261080] 2---2
    2017-12-04 17:10:10.800 DownImage[3289:261096] 5---5
    2017-12-04 17:10:10.840 DownImage[3289:261080] 7---7
    2017-12-04 17:10:10.844 DownImage[3289:261082] 6---6
    2017-12-04 17:10:10.846 DownImage[3289:261096] 3---3
    2017-12-04 17:10:10.888 DownImage[3289:261096] 8---8
    2017-12-04 17:10:10.945 DownImage[3289:261080] 9---9
    

    很明显,无任何处理情况下,end最先被打印出来,由于网络请求的异步回调,然后各个网络请求的回调顺序是无序的。

    2.使用GCD的dispatch_group_t

    viewDidLoad里:

    //2.group
        UIButton *Btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
        Btn2.frame = CGRectMake(100, 200, 100, 40);
        Btn2.backgroundColor = [UIColor grayColor];
        [Btn2 setTitle:@"group--" forState:UIControlStateNormal];
        [Btn2 addTarget:self action:@selector(Btn2) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:Btn2];
    

    实现:

    //2.group--
    -(void)Btn2{
        NSString *str = @"http://www.jianshu.com/p/6930f335adba";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];
        
        dispatch_group_t downloadGroup = dispatch_group_create();
        for (int i=0; i<10; i++) {
            dispatch_group_enter(downloadGroup);
            
            NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                
                NSLog(@"%d---%d",i,i);
                dispatch_group_leave(downloadGroup);
                
            }];
            
            [task resume];
        }
        
        dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
            NSLog(@"end");
        });
    }
    

    运行看看控制台输出:

    2017-12-04 17:14:46.984 DownImage[3289:265374] 2---2
    2017-12-04 17:14:46.987 DownImage[3289:265370] 1---1
    2017-12-04 17:14:47.052 DownImage[3289:265383] 5---5
    2017-12-04 17:14:47.065 DownImage[3289:265370] 4---4
    2017-12-04 17:14:47.111 DownImage[3289:265379] 3---3
    2017-12-04 17:14:47.121 DownImage[3289:265383] 6---6
    2017-12-04 17:14:47.169 DownImage[3289:265383] 7---7
    2017-12-04 17:14:47.192 DownImage[3289:265370] 9---9
    2017-12-04 17:14:47.321 DownImage[3289:265383] 8---8
    2017-12-04 17:14:47.747 DownImage[3289:265374] 0---0
    2017-12-04 17:14:47.747 DownImage[3289:261033] end
    
    2017-12-04 17:15:14.576 DownImage[3289:265942] 3---3
    2017-12-04 17:15:14.626 DownImage[3289:265936] 2---2
    2017-12-04 17:15:14.647 DownImage[3289:265944] 4---4
    2017-12-04 17:15:14.648 DownImage[3289:265936] 0---0
    2017-12-04 17:15:14.657 DownImage[3289:265943] 1---1
    2017-12-04 17:15:14.709 DownImage[3289:265944] 5---5
    2017-12-04 17:15:14.728 DownImage[3289:265944] 6---6
    2017-12-04 17:15:14.734 DownImage[3289:265944] 7---7
    2017-12-04 17:15:14.738 DownImage[3289:265943] 8---8
    2017-12-04 17:15:14.816 DownImage[3289:265944] 9---9
    2017-12-04 17:15:14.816 DownImage[3289:261033] end
    
    

    从上两次输出可以看出,end确实是在所有网络请求之后才输出出来,这也是符合了我们的需求。

    代码中我们只添加了4行代码

    dispatch_group_t downloadGroup = dispatch_group_create();
    dispatch_group_enter(downloadGroup);
    dispatch_group_leave(downloadGroup);
    dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
        });
    

    对以上4行代码可理解为:创建一个dispatch_group_t, 每次网络请求前先dispatch_group_enter,请求回调后再dispatch_group_leave,对于enter和leave必须配合使用,有几次enter就要有几次leave,否则group会一直存在。当所有enter的block都leave后,会执行dispatch_group_notify的block。

    3.使用GCD的信号量dispatch_semaphore_t
    //3.semaphore
        UIButton *Btn3 = [UIButton buttonWithType:UIButtonTypeCustom];
        Btn3.frame = CGRectMake(100, 300, 100, 40);
        Btn3.backgroundColor = [UIColor grayColor];
        [Btn3 setTitle:@"semaphore" forState:UIControlStateNormal];
        [Btn3 addTarget:self action:@selector(Btn3) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:Btn3];
    
    //3.semaphore--
    -(void)Btn3{
        NSString *str = @"http://www.jianshu.com/p/6930f335adba";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];
        
        dispatch_semaphore_t sem = dispatch_semaphore_create(0);
        for (int i=0; i<10; i++) {
            
            NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                
                NSLog(@"%d---%d",i,i);
                count++;
                if (count==10) {
                    dispatch_semaphore_signal(sem);
                    count = 0;
                }
                
            }];
            
            [task resume];
        }
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"end");
        });
    }
    

    运行看看控制台输出:

    2017-12-04 17:36:49.098 DownImage[3428:283651] 2---2
    2017-12-04 17:36:49.144 DownImage[3428:284210] 0---0
    2017-12-04 17:36:49.152 DownImage[3428:284213] 3---3
    2017-12-04 17:36:49.158 DownImage[3428:283651] 1---1
    2017-12-04 17:36:49.167 DownImage[3428:284210] 4---4
    2017-12-04 17:36:49.235 DownImage[3428:284213] 8---8
    2017-12-04 17:36:49.249 DownImage[3428:283651] 5---5
    2017-12-04 17:36:49.252 DownImage[3428:283651] 7---7
    2017-12-04 17:36:49.324 DownImage[3428:283651] 9---9
    2017-12-04 17:36:49.468 DownImage[3428:284214] 6---6
    2017-12-04 17:36:49.469 DownImage[3428:283554] end
    
    2017-12-04 17:37:11.554 DownImage[3428:284747] 0---0
    2017-12-04 17:37:11.555 DownImage[3428:284733] 1---1
    2017-12-04 17:37:11.627 DownImage[3428:284748] 5---5
    2017-12-04 17:37:11.661 DownImage[3428:284748] 2---2
    2017-12-04 17:37:11.688 DownImage[3428:284747] 4---4
    2017-12-04 17:37:11.709 DownImage[3428:284747] 6---6
    2017-12-04 17:37:11.770 DownImage[3428:284733] 7---7
    2017-12-04 17:37:11.774 DownImage[3428:284733] 8---8
    2017-12-04 17:37:11.824 DownImage[3428:284747] 9---9
    2017-12-04 17:37:11.899 DownImage[3428:284733] 3---3
    2017-12-04 17:37:11.900 DownImage[3428:283554] end
    

    从输出可以看出,这样的方法也是满足我们的需求的,在这个方法中,我们使用了

    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    dispatch_semaphore_signal(sem);
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    

    对这三句代码可以这样理解:dispatch_semaphore信号量为基于计数器的一种多线程同步机制。如果semaphore计数大于等于1,计数-1,返回,程序继续运行。如果计数为0,则等待。dispatch_semaphore_signal(semaphore)为计数+1操作,dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)为设置等待时间,这里设置的等待时间是一直等待。

    对于以上代码通俗一点就是,开始为0,等待,等10个网络请求都完成了,dispatch_semaphore_signal(semaphore)为计数+1,然后计数-1返回,程序继续执行。 (这里也就是为什么有个count变量的原因,记录网络回调的次数,回调10次之后再发信号量,使后面程序继续运行)。

    4.考虑新需求,10个网络请求顺序回调。

    需求需要顺序回调,即执行完第一个网络请求后,第二个网络请求回调才可被执行,简单来讲就是输出得是0,1,2,3...9这种方式的。

    对于这个需求我也是根据自己最近做的项目来提的,因为网络请求回调的异步性,我们虽可以控制网络请求的顺序执行,却不能控制它的完成回调顺序。这就有点伤了,目前我项目是找到了解决方案,但这个问题还没有找到解决办法,提出来跟大家讨论一下。(请忽略网络请求执行,回调,在回调里请求下一个接口的办法,讨论还有没有别的方法,最好show the code).

    最后,贴点NSOperation的代码,为了解决新需求所写,由于网络请求回调异步性不能满足需求,但若不是网络请求等异步回调的方式,这样的做法是可以的,大家可以试试.

    //4.NSOperation
        UIButton *Btn4 = [UIButton buttonWithType:UIButtonTypeCustom];
        Btn4.frame = CGRectMake(100, 400, 100, 40);
        Btn4.backgroundColor = [UIColor grayColor];
        [Btn4 setTitle:@"NSOperation" forState:UIControlStateNormal];
        [Btn4 addTarget:self action:@selector(Btn4) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:Btn4];
    
    //4.NSOperation
    -(void)Btn4{
        NSString *str = @"http://www.jianshu.com/p/6930f335adba";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];
        
        NSMutableArray *operationArr = [[NSMutableArray alloc]init];
        for (int i=0; i<10; i++) {
            NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
                NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                    
                    NSLog(@"%d---%d",i,i);
                    
                }];
                
                [task resume];
    
                //非网络请求
                NSLog(@"noRequest-%d",i);
            }];
            
            [operationArr addObject:operation];
            if (i>0) {
                NSBlockOperation *operation1 = operationArr[i-1];
                NSBlockOperation *operation2 = operationArr[i];
                [operation2 addDependency:operation1];
            }
        }
        
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        [queue addOperations:operationArr waitUntilFinished:NO];  //YES会阻塞当前线程
    #warning - 绝对不要在应用主线程中等待一个Operation,只能在第二或次要线程中等待。阻塞主线程将导致应用无法响应用户事件,应用也将表现为无响应。
        
    }
    

    运行结果:

    2017-12-04 18:03:10.224 DownImage[3584:304363] noRequest-0
    2017-12-04 18:03:10.226 DownImage[3584:304362] noRequest-1
    2017-12-04 18:03:10.226 DownImage[3584:304363] noRequest-2
    2017-12-04 18:03:10.231 DownImage[3584:304363] noRequest-3
    2017-12-04 18:03:10.232 DownImage[3584:304362] noRequest-4
    2017-12-04 18:03:10.233 DownImage[3584:304362] noRequest-5
    2017-12-04 18:03:10.233 DownImage[3584:304363] noRequest-6
    2017-12-04 18:03:10.234 DownImage[3584:304363] noRequest-7
    2017-12-04 18:03:10.235 DownImage[3584:304363] noRequest-8
    2017-12-04 18:03:10.236 DownImage[3584:304363] noRequest-9
    2017-12-04 18:03:10.408 DownImage[3584:304597] 2---2
    2017-12-04 18:03:10.408 DownImage[3584:304597] 0---0
    2017-12-04 18:03:10.409 DownImage[3584:304597] 1---1
    2017-12-04 18:03:10.461 DownImage[3584:304597] 5---5
    2017-12-04 18:03:10.476 DownImage[3584:304363] 4---4
    2017-12-04 18:03:10.477 DownImage[3584:304365] 6---6
    2017-12-04 18:03:10.518 DownImage[3584:304365] 7---7
    2017-12-04 18:03:10.537 DownImage[3584:304596] 8---8
    2017-12-04 18:03:10.547 DownImage[3584:304362] 9---9
    2017-12-04 18:03:11.837 DownImage[3584:304362] 3---3
    
    2017-12-04 18:04:27.699 DownImage[3584:306401] noRequest-0
    2017-12-04 18:04:27.700 DownImage[3584:306405] noRequest-1
    2017-12-04 18:04:27.701 DownImage[3584:306401] noRequest-2
    2017-12-04 18:04:27.701 DownImage[3584:306405] noRequest-3
    2017-12-04 18:04:27.702 DownImage[3584:306401] noRequest-4
    2017-12-04 18:04:27.702 DownImage[3584:306405] noRequest-5
    2017-12-04 18:04:27.703 DownImage[3584:306401] noRequest-6
    2017-12-04 18:04:27.703 DownImage[3584:306401] noRequest-7
    2017-12-04 18:04:27.704 DownImage[3584:306401] noRequest-8
    2017-12-04 18:04:27.704 DownImage[3584:306401] noRequest-9
    2017-12-04 18:04:27.772 DownImage[3584:306397] 2---2
    2017-12-04 18:04:27.779 DownImage[3584:306401] 0---0
    2017-12-04 18:04:27.782 DownImage[3584:306409] 1---1
    2017-12-04 18:04:27.800 DownImage[3584:306405] 3---3
    2017-12-04 18:04:27.851 DownImage[3584:306401] 6---6
    2017-12-04 18:04:27.855 DownImage[3584:306397] 5---5
    2017-12-04 18:04:27.915 DownImage[3584:306397] 7---7
    2017-12-04 18:04:27.951 DownImage[3584:306397] 9---9
    2017-12-04 18:04:27.953 DownImage[3584:306405] 8---8
    2017-12-04 18:04:28.476 DownImage[3584:306409] 4---4
    
    5.还是使用信号量semaphore完成4的需求
    //5.semaphore---order
        UIButton *Btn5 = [UIButton buttonWithType:UIButtonTypeCustom];
        Btn5.frame = CGRectMake(100, 500, 100, 40);
        Btn5.backgroundColor = [UIColor grayColor];
        [Btn5 setTitle:@"order" forState:UIControlStateNormal];
        [Btn5 addTarget:self action:@selector(Btn5) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:Btn5];
    
    //5.semaphore--order
    -(void)Btn5{
        NSString *str = @"http://www.jianshu.com/p/6930f335adba";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];
        
        dispatch_semaphore_t sem = dispatch_semaphore_create(0);
        for (int i=0; i<10; i++) {
            
            NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                
                NSLog(@"%d---%d",i,i);
                dispatch_semaphore_signal(sem);
            }];
            
            [task resume];
            dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"end");
        });
    }
    

    我们看看运行结果:

    2017-12-05 10:17:28.175 DownImage[938:51296] 0---0
    2017-12-05 10:17:28.331 DownImage[938:51289] 1---1
    2017-12-05 10:17:28.506 DownImage[938:51289] 2---2
    2017-12-05 10:17:28.563 DownImage[938:51289] 3---3
    2017-12-05 10:17:28.662 DownImage[938:51289] 4---4
    2017-12-05 10:17:28.733 DownImage[938:51296] 5---5
    2017-12-05 10:17:28.792 DownImage[938:51296] 6---6
    2017-12-05 10:17:28.856 DownImage[938:51286] 7---7
    2017-12-05 10:17:29.574 DownImage[938:51289] 8---8
    2017-12-05 10:17:29.652 DownImage[938:51286] 9---9
    2017-12-05 10:17:29.653 DownImage[938:45252] end
    
    2017-12-05 10:17:46.341 DownImage[938:51608] 0---0
    2017-12-05 10:17:47.967 DownImage[938:51607] 1---1
    2017-12-05 10:17:48.038 DownImage[938:51603] 2---2
    2017-12-05 10:17:48.132 DownImage[938:51603] 3---3
    2017-12-05 10:17:48.421 DownImage[938:51608] 4---4
    2017-12-05 10:17:48.537 DownImage[938:51289] 5---5
    2017-12-05 10:17:48.646 DownImage[938:51289] 6---6
    2017-12-05 10:17:48.939 DownImage[938:51289] 7---7
    2017-12-05 10:17:50.537 DownImage[938:51607] 8---8
    2017-12-05 10:17:50.615 DownImage[938:51289] 9---9
    2017-12-05 10:17:50.616 DownImage[938:45252] end
    

    我们对比 3 的代码,3 中我们只在最后也就是循环结束后调用dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER),循环中当网络请求回调10次(也就是都回调完)后,使传入的信号量加1:( dispatch_semaphore_signal(sem) ),这时等待结束,然后进行后续的操作。

    在这个方法里,我们每一次遍历,都让其dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER),这个时候线程会等待,阻塞当前线程,直到dispatch_semaphore_signal(sem)调用之后,而我们dispatch_semaphore_signal(sem)是在网络请求的回调里调用的,所以这个方法的逻辑是:

    遍历—>发起任务—>等待—>任务完成信号量加1—>等待结束,开始下一个任务
    发起任务—>等待—>任务完成信号量加1—>等待结束,开始下一个任务
    发起任务—>等待—>任务完成信号量加1—>等待结束,开始下一个任务

    这样循环的模式,一个任务完成才能接着去做下面的任务,满足我们的需求。

    但我们也要发现这样一个问题,我们使用这种方式,可以明显感觉出整个过程需要花费的时间大大增加了,不像我们 3 中同时(几乎)开启任务等待完成回调,这里是一个网络请求发出,等待,完成后发出第二个网络请求,等待,完成后再发出第三个,这样我们等待的时间是10个网络请求每一个回调时间的和,在时间上大大增加了消耗,而且对于dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER),它是会阻塞线程的,我们如果需要在网络请求完成后修改UI,那这种方式会影响我们的界面交互,接下来我们对比一下两者时间消耗:

    3-------------3----------3-------
    2017-12-05 10:29:51.178 DownImage[938:56971] 2---2
    2017-12-05 10:29:51.193 DownImage[938:57200] 0---0
    2017-12-05 10:29:51.202 DownImage[938:56631] 3---3
    2017-12-05 10:29:51.248 DownImage[938:56971] 1---1
    2017-12-05 10:29:51.262 DownImage[938:56971] 5---5
    2017-12-05 10:29:51.291 DownImage[938:56631] 6---6
    2017-12-05 10:29:51.375 DownImage[938:56631] 7---7
    2017-12-05 10:29:51.384 DownImage[938:56631] 4---4
    2017-12-05 10:29:51.434 DownImage[938:56971] 8---8
    2017-12-05 10:29:51.487 DownImage[938:57199] 9---9
    2017-12-05 10:29:51.488 DownImage[938:45252] end
    
    5-------------5----------5-------
    2017-12-05 10:29:52.190 DownImage[938:56631] 0---0
    2017-12-05 10:29:52.304 DownImage[938:57199] 1---1
    2017-12-05 10:29:52.432 DownImage[938:56971] 2---2
    2017-12-05 10:29:52.520 DownImage[938:56971] 3---3
    2017-12-05 10:29:52.576 DownImage[938:56631] 4---4
    2017-12-05 10:29:52.628 DownImage[938:56971] 5---5
    2017-12-05 10:29:52.706 DownImage[938:56631] 6---6
    2017-12-05 10:29:52.764 DownImage[938:56971] 7---7
    2017-12-05 10:29:52.853 DownImage[938:56631] 8---8
    2017-12-05 10:29:52.925 DownImage[938:56971] 9---9
    2017-12-05 10:29:52.926 DownImage[938:45252] end
    

    看得出3花费时间为51.488 - 51.178约300多ms
    --- ---5花费时间为52.926 - 52.190约700多ms

    所以大家还请谨慎使用。

    相关文章

      网友评论

      • hgl:第3个问题,当几个网络回调同时回来,而变量count又不是原子性的时候,会不会有问题
      • 张科_Zack:方法5,这么做其实和同步网络请求没啥差别。
        如果楼主想实现顺序回调结果可以讲给次的回调block和返回数据用数组保存起来。在全部网络请求结束后,在遍历保存block、和数据的数组。
      • 张科_Zack:方法5,这么做其实和同步网络请求没啥差别。
        如果楼主想实现顺序回调结果可以讲给次的回调block和返回数据用数组保存起来。在全局网络请求结束后,在遍历保存block、和数据的数组。
      • Lol刀妹:可以,总结得不错:smile:
      • chokshen:请教大神一个dispatch_group_t的问题,我的是同时上传多张图片,for循环调用上传图片接口,按照你的这种写法,调用上传图片接口前enter,回调上传结果后leave(主线程回调),dispatch_group_notify为什么在回调上传结果之前就执行了?不应该等所有结果回调完再执行么?
        4d0f908939bc:dispatch_group_notify 的位置放到最后面了吗?如果写在最开始,这是 group 的计数为0,直接就执行了。
        _清墨:@chokshen 确定要配对使用,多少个enter,多少个leave
      • perfectCopy:我之前一直用kvo的,这是被逼出来的方法.希望不要被喷....
        张科_Zack:我刚看到这个需求时想的也是kvo
        perfectCopy:@_清墨 我现在知道用心好凉了,不怕了 哈哈
        _清墨:@perfectCopy kvo至少能实现:mask:,不过这怕是被看到:sweat_smile::sweat_smile::sweat_smile:哈哈
      • 安静守护你:addDependency 添加依赖控制线程执行顺序
        4d0f908939bc:封装在 NSOperation 内的任务时异步的,addDependency 只能控制异步任务执行的顺序,并不能控制异步任务完成的顺序
        _清墨:那个就涉及的是nsoperation了,控制线程执行顺序不难,这里主要还是讲控制线程执行后回调的顺序
      • PGOne爱吃饺子:大佬,你的这个需求:4.考虑新需求,10个网络请求顺序回调。
        这种方案可不可以,重新开个线程,搞个串行队列应该也是可以解决你的这种问题的
        PGOne爱吃饺子:对对,忘记了回调顺序也要按顺序的,谢谢大佬
        _清墨:任务的执行顺序是对的,任务完成的回调顺序不一定
      • 搜捕儿:给大佬点赞~👍
      • PGOne爱吃饺子:这篇文章楼主写的真不错,给你个大赞
        _清墨:@PGOne爱吃饺子 thank you
      • vision_colion:还可以用rac做,也比较简单
        Juice007:对,RAC的concat解决起来很简便
      • liuyanhongwl:4那种需求“10个网络请求异步执行,顺序回调”可以用NSConditionLock处理
        _清墨:@liuyanhongwl :+1: :+1: :+1: 很棒,这样实现比5那样方式好许多
        liuyanhongwl:@_清墨 不是加在请求前面,可以在所有回调加入到一个自定义并发队列中,在队列任务执行前进行条件加锁。

        代码如下:
        _lock = [[NSConditionLock alloc] initWithCondition:0];
        dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        for (int i=0; i<10; i++) {
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        dispatch_async(queue, ^{
        [self.lock lockWhenCondition:i];
        NSLog(@"%d---%d",i,i);
        [self.lock unlockWithCondition:i+1];
        });
        }];
        [task resume];
        }
        _清墨:简单去了解了一下,是可以的,不过对于这种for类型的,lock也只能加在外面,等于每次lock,等回调回来再unlock,然后进行下一次的任务,lock,回调回来unlock。这种方式还是跟5一样,需要等待的时间消耗长。
      • 2772fbfad660:有完整的Demo么, 发一下. 谢谢
        _清墨:@heavenbird 是不是没在外写 count 变量,int count;
        2772fbfad660:@_清墨 3号代码段跑不起来.
        _清墨:文章中已给出全部代码,viewDidLoad中创建了5个按钮,5个按钮分别对应5个方法,代码已全在上面。

      本文标题:iOS多个网络请求完成后执行下一步

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