iOS当多个网络请求完成后执行下一步的方法详解

前言

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

网络请求的任务是提交给子线程异步处理了,网络请求这样的任务也就快速执行完毕了,但是网络请求是一个任务,处理收到的网络响应又是一个任务,注意不要把这两个过程混为一谈。

如下载多个图片,下载完了才能展示,今天我们就来研究一下这个问题的解决方案。

解决方法

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

所以大家还请谨慎使用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • iOS判断网络请求超时的方法

    本文介绍了iOS判断网络请求超时的方法,代码具体如下: + (AFHTTPRequestOperation *)requestOperationWithUrl:(NSString *)url requetMethod:(NSString *)method paramData:(NSDictionary *)aParamData constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block success

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

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

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

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

  • iOS当多个网络请求完成后执行下一步的方法详解

    前言 在开发中,我们很容易遇到这样的需求,需要我们同时做多个网络请求,所有网络请求都完成后才能进行下一步的操作. 网络请求的任务是提交给子线程异步处理了,网络请求这样的任务也就快速执行完毕了,但是网络请求是一个任务,处理收到的网络响应又是一个任务,注意不要把这两个过程混为一谈. 如下载多个图片,下载完了才能展示,今天我们就来研究一下这个问题的解决方案. 解决方法 1.首先,我们创建一个项目,然后做一般性的做法,不做任何处理去连续请求一个接口10次: 先在viewDidLoad中创建第一种情况.

  • IOS 出现问题POST网络请求状态code:500的解决方法

    IOS 出现问题POST网络请求状态code:500的解决方法 前言: iOS 10 用 [NSURLSession uploadTaskWithRequest:request fromData:jsondata completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error){}]; 进行post网络请求时 出现 500 错误 出现500 的错误

  • Flutter网络请求Dio库的使用及封装详解

    目录 一.项目目录结构 二.封装思路: 三.添加依赖 四.简单实现网络请求 五.实现登录注册服务 六.使用service服务 Dart语言内置的HttpClient实现了基本的网络请求相关的操作.但HttpClient本身功能较弱,很多网络请求常用功能都不支持,因此在实际项目中,我们更多是使用dio库实现网络请求. 注:Flutter官网同样推荐在项目中使用Dio库. Dio文档地址: pub.dev地址:dio | Dart Package 一.项目目录结构 文件夹 功能 components

  • JAVA发送http get/post请求,调用http接口、方法详解

    三个例子 -JAVA发送http get/post请求,调用http接口.方法 例1:使用 HttpClient (commons-httpclient-3.0.jar jar下载地址:http://xiazai.jb51.net/201904/yuanma/commons-httpclient-3.0.rar import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOE

  • postfixadmin忘记密码后的修改密码方法详解

    本文实例讲述了postfixadmin忘记密码后的修改密码方法.分享给大家供大家参考,具体如下: Postfix Admin 是一个基于Web的 Postfix 邮件发送服务器的管理工具,可以直接管理 Postfix 的虚拟域名和用户. 由于有一段时间没使用postfixadmin增删用户了, 突然需使用时忘记了管理密码,  使用老外的方式直接在数据库里修改密码, 后登录成功 php源码: <?php echo md5crypt("新密码"); // md5crypt // Ac

  • iOS中使用NSProgress类来创建UI进度条的方法详解

    一.引言 在iOS7之前,系统一直没有提供一个完整的框架来描述任务进度相关的功能.这使得在开发中进行耗时任务进度的监听将什么麻烦,在iOS7之后,系统提供了NSProgress类来专门报告任务进度. 二.创建单任务进度监听器 单任务进度的监听是NSProgress最简单的一种运用场景,我们来用定时器模拟一个耗时任务,示例代码如下: @interface ViewController () { NSProgress * progress; } @end @implementation ViewCo

  • Yii2实现增删改查后留在当前页的方法详解

    前言 实现增删改查操作成功后仍留在当前页,能给用户一个良好的体验.但是 Yii2 框架本身是没有在增删改查操作成功后仍留在当前页的效果的,要实现这样的一个效果得自己写.我的原则是不动核心代码,始终坚持自己的原则,现实现了我把它分享出来.殊途同归,如有更好的实现方法,欢迎交流. 需求分析 一.实现增删改查后操作成功后仍然留在当前页面. 1.链接的效果图 封装代码 共有两个文件ActionColumn.php和Helper.php1.ActionColumn.php文件 <?php use Clos

  • iOS应用开发中对UIImage进行截取和缩放的方法详解

    截取UIImage指定大小区域 最近遇到这样的需求:从服务器获取到一张照片,只需要显示他的左半部分,或者中间部分等等.也就是截取UIImage指定大小区域. UIImage扩展: 我的解决方案是对UIImage进行扩展.通过CGImageRef和CGImage完成截取,调用的方法是:CGImageCreateWithImageInRect.扩展类叫UIImage+Crop,具体代码如下: UIImage+Crop.h #import <UIKit/UIKit.h> typedef NS_ENU

  • IOS开发中异步网络请求上实现同步逻辑

    IOS开发中异步网络请求上实现同步逻辑 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不需要上传了,直接报错. 之前ASI的网络库中是有同步请求的接口,所以很好处理,AFNetwork的网络库只有异步的网络请求,该怎么实现呢? 1.循环异步拼组 - (void)uploadFile:(NSArray *)imageArray atIndex:(NSInteger)index imagesCount:(NSInteger

随机推荐