GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操做的机制。它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务。html
GCD中的FIFO队列称为dispatch queue,它能够保证先进来的任务先获得执行(但不保证必定先执行结束)。ios
经过与线程池的配合,dispatch queue分为下面两种:并发
1. Basic Managementapp
咱们能够经过dispatch_queue_cretae来建立队列,而后用dispatch_release释放。好比下面两段代码分别建立串行队列和并行队列:异步
dispatch_queue_t serialQ = dispatch_queue_create("eg.gcd.SerialQueue", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQ, ^{ // Code here }); dispatch_release(serialQ); dispatch_queue_t concurrentQ = dispatch_queue_create("eg.gcd.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(concurrentQ, ^{ // Code here }); dispatch_release(concurrentQ);
而系统默认就有一个串行队列main_queue和并行队列global_queue:async
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t mainQ = dispatch_get_main_queue();
一般,咱们能够在global_queue中作一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,没法响应用户操做:ide
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // long-running task dispatch_async(dispatch_get_main_queue(), ^{ // update UI }); });
上面提到dispatch_async这个接口,用来提交blcok给指定queue进行异步执行。这个接口会在成功提交block后当即返回,而后继续执行下去。因为block是定义在栈上的,因此须要将其复制到堆上,见这里。函数
与之相对应的是dispatch_sync接口,提交block以供同步执行。这个接口会等到block执行结束才返回,因此不须要复制block。So,若是在调用该接口在当前queue上指派任务,就会致使deadlock。维基百科上给了段示例代码:测试
dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.unique.identifier", NULL ); dispatch_sync( exampleQueue,^{ dispatch_sync( exampleQueue,^{ printf("I am now deadlocked...\n"); });}); dispatch_release( exampleQueue );
若是追求的是并发,那么dispatch_sync有什么用呢?关于dispatch_sync的用途,SO上有讨论。动画
2. Normal Control
若是没有记错的话,在iOS Con 2012上,大众点评的同窗分享了个Topic叫《iOS开发最佳实践》,开篇讲singleton实现的演进(怎么演进都有能够挑的刺),后面转折说要把精力放到用户看获得的地方。
若是把singleton和best practice放在一块儿,那么我很容易联想到dispatch_once这个函数,它能够保证整个应用程序生命周期中某段代码只被执行一次!
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // code to be executed once });
有时候咱们须要等个几秒钟而后作个动画或者给个提示,这时候能够用dispatch_after这个函数:
double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // code to be executed on the main queue after delay });
经过dispatch_set_target_queue函数能够设置一个dispatch queue的优先级,或者指定一个dispatch source相应的事件处理提交到哪一个queue上。
dispatch_set_target_queue(serialQ, globalQ);
执行某个代码片断若干次。
dispatch_apply(10, globalQ, ^(size_t index) { // do sth. 10 times });
Dispatch Group机制容许咱们监听一组任务是否完成:
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, concurrentQ, blk0); dispatch_group_async(group, concurrentQ, blk1); dispatch_group_async(group, concurrentQ, blk2); dispatch_group_notify(group, mainQ, ^{ // update UI }); dispatch_release(group);
或者说同步地等待一段时间看是否结束:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);
dispatch_group_wait(group, time);
经过dispatch_barrier_async函数提交的任务会等它前面的任务执行结束才开始,而后它后面的任务必须等它执行完毕才能开始。
dispatch_async(concurrentQ, blk0);
dispatch_async(concurrentQ, blk1);
dispatch_barrier_async(concurrentQ, blk_barrier);
dispatch_async(concurrentQ, blk2);
原文连接:http://blog.csdn.net/jasonblog/article/details/7816999
最后,推荐一个神器。
内测宝, 我的以为比TestFlight更简单好用,开发者只须要简单把打好的ipa包上传上去,生成二维码,测试人员在手机上扫码二维码,就能够直接安装最新的测试版本了,好用的让人想哭。