一、延时执行
1、iOS常见的延时执行有2种方式
(1)调用NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // 2秒后再调用self的run方法
(2)使用GCD函数
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 2秒后异步执行这里的代码... });
注意:这里异步执行的代码,是放在主队列中执行的
2、GCD延时执行
(1)主队列执行
1 NSLog(@"延时开始前...."); 2 // 输入dispatch_after 3 // 从当前时间,延迟2.0秒之后,给主队列添加一个任务(此任务会在主线程上【异步】运行) 4 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 5 NSLog(@"%@", [NSThread currentThread]); 6 }); 7 NSLog(@"延时设置结束....");
输出结果:
延时开始前....
延时设置结束....
<NSThread: 0x8d53ea0>{name = (null), num = 1}
从结果看出,延时操作是在主队列异步运行的,因为 dispatch_after 里边有个 dispatch_get_main_queue参数
(2)异步任务,开启子线程执行延时
1 // 1. 队列 2 dispatch_queue_t q = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT); 3 4 // 2. 异步任务 5 dispatch_async(q, ^{ 6 NSLog(@"延时开始前.... %@", [NSThread currentThread]); 7 // 输入dispatch_after 8 // 从当前时间,延迟2.0秒之后,给主队列添加一个任务(此任务会在主线程上【异步】运行) 9 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 10 NSLog(@"%@", [NSThread currentThread]); 11 }); 12 NSLog(@"延时设置结束...."); 13 });
输出结果:
延时开始前.... <NSThread: 0x8c3f870>{name = (null), num = 2}
延时设置结束....
<NSThread: 0x8c23a80>{name = (null), num = 1}
结果说明,延时操作回到了主线程执行
(3)延时操作默认在主队列执行的优点:
调用的方法通常是跟UI有关的,例如提示用户等;
不了解GCD或者多线程的人,可以直接填空即可。
(4)dispatch_after 延时操作应用场景
例如:游戏后台需要做一些随机的事件,需要在某个时间后,调用方法。
一会儿冒个花,冒个什么的,无意间做了什么操作之后
二、队列组
(1)有这么1种需求
首先:分别异步执行2个耗时的操作
其次:等2个异步操作都执行完毕后,再回到主线程执行操作
如果想要快速高效地实现上述需求,可以考虑用队列组
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 执行1个耗时的异步操作 }); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 执行1个耗时的异步操作 }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的异步操作都执行完毕后,回到主线程... });
(2)现实例子
模拟下载多个文件
1 // 1. 队列 2 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 3 4 // 2. 队列组 5 dispatch_group_t group = dispatch_group_create(); 6 7 // 3. 任务添加到组 8 dispatch_group_async(group, q, ^{ 9 [NSThread sleepForTimeInterval:5.0]; 10 NSLog(@"下载三国演义中..."); 11 }); 12 dispatch_group_async(group, q, ^{ 13 [NSThread sleepForTimeInterval:2.0]; 14 NSLog(@"下载西游记中..."); 15 }); 16 dispatch_group_async(group, q, ^{ 17 [NSThread sleepForTimeInterval:3.0]; 18 NSLog(@"下载梅中..."); 19 }); 20 21 // 所有的书下载完成后通知用户 22 // 1> 用group统一监听所有的异步任务执行情况,在全部完成后通知 23 // 2> 注意:所有任务结束后,通常是要通知用户,涉及到UI的交互,因此队列应该使用主队列! 24 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 25 // 通常是要通知用户,涉及到UI的交互 26 NSLog(@"所有书籍都下载完毕! %@", [NSThread currentThread]); 27 });
输出结果:
下载西游记中...
下载梅中...
下载三国演义中...
所有书籍都下载完毕! <NSThread: 0x8c1beb0>{name = (null), num = 1}
在平常经常用的队列和任务之间加队列组。
注意:dispatch_group_notify方法的参数为dispatch_get_main_queue,放到主队列通知用户