block的定义有点象函数指针,差别是用 ^ 替代了函数指针的 * 号,如下所示:
1 2 3 4 5 6 7 8 9 // 申明变量 (void) (^loggerBlock)(void); // 定义 loggerBlock = ^{ NSLog(@"Hello world"); }; // 调用 loggerBlock();但是大多数时候,我们通常使用内联的方式来定义block,即将它的程序块写在调用的函数里面,例如这样:
1 2 3 dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something });从上面大家可以看出,block有如下特点:
程序块可以在代码中以内联的方式来定义。程序块可以访问在创建它的范围内的可用的变量。为了方便地使用GCD,苹果提供了一些方法方便我们将block放在主线程 或 后台线程执行,或者延后执行。使用的例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // 后台执行: dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something }); // 主线程执行: dispatch_async(dispatch_get_main_queue(), ^{ // something }); // 一次性执行: static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // code to be executed once }); // 延迟2秒执行: 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_queue_t 也可以自己定义,如要要自定义queue,可以用dispatch_queue_create方法,示例如下:
1 2 3 4 5 dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL); dispatch_async(urls_queue, ^{ // your code }); dispatch_release(urls_queue);另外,GCD还有一些高级用法,例如让后台2个线程并行执行,然后等2个线程都结束后,再汇总执行结果。这个可以用dispatch_group, dispatch_group_async 和 dispatch_group_notify来实现,示例如下:
1 2 3 4 5 6 7 8 9 10 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 并行执行的线程一 }); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 并行执行的线程二 }); dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{ // 汇总结果 });默认情况下,在程序块中访问的外部变量是复制过去的,即写操作不对原变量生效。但是你可以加上 __block来让其写操作生效,示例代码如下:
1 2 3 4 5 6 __block int a = 0; void (^foo)(void) = ^{ a = 1; } foo(); // 这里,a的值被修改为1使用block的另一个用处是可以让程序在后台较长久的运行。在以前,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是应用可以调用UIApplication的beginBackgroundTaskWithExpirationHandler方法,让app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。
让程序在后台长久运行的示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // AppDelegate.h文件 @property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask; // AppDelegate.m文件 - (void)applicationDidEnterBackground:(UIApplication *)application { [self beingBackgroundUpdateTask]; // 在这里加上你需要长久运行的代码 [self endBackgroundUpdateTask]; } - (void)beingBackgroundUpdateTask { self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self endBackgroundUpdateTask]; }]; } - (void)endBackgroundUpdateTask { [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask]; self.backgroundUpdateTask = UIBackgroundTaskInvalid; }总体来说,GCD能够极大地方便开发者进行多线程编程。大家应该尽量使用GCD来处理后台线程和UI线程的交互。
文章源地址:http://blog.devtang.com/blog/2012/02/22/use-gcd/
转载于:https://www.cnblogs.com/AlienY/p/4514504.html
相关资源:iOS中block的定义与使用