GCD/Block

来源:互联网 发布:win10网络连接不上 编辑:程序博客网 时间:2024/06/05 02:56

GCD

唐巧的博客

block 的定义

block 的定义有点象函数指针,差别是用 ^ 替代了函数指针的 * 号,如下所示:

// 申明变量(void) (^loggerBlock)(void);// 定义loggerBlock = ^{    NSLog(@"Hello world");};// 调用loggerBlock();

但是大多数时候,我们通常使用内联的方式来定义 block,即将它的程序块写在调用的函数里面,例如这样:

dispatch_async(dispatch_get_global_queue(0, 0), ^{     // something});

从上面大家可以看出,block 有如下特点:

  • 程序块可以在代码中以内联的方式来定义。
  • 程序块可以访问在创建它的范围内的可用的变量。

系统提供的 dispatch 方法

为了方便地使用 GCD,苹果提供了一些方法方便我们将 block 放在主线程 或 后台线程执行,或者延后执行。使用的例子如下:

//  后台执行: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 方法,示例如下:

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 来实现,示例如下:

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 之外的变量

默认情况下,在程序块中访问的外部变量是复制过去的,即写操作不对原变量生效。但是你可以加上 __block 来让其写操作生效,示例代码如下:

__block int a = 0;void  (^foo)(void) = ^{     a = 1;}foo();// 这里,a 的值被修改为 1

后台运行

使用 block 的另一个用处是可以让程序在后台较长久的运行。在以前,当 app 被按 home 键退出后,app 仅有最多 5 秒钟的时候做一些保存或清理资源的工作。但是应用可以调用 UIApplicationbeginBackgroundTaskWithExpirationHandler方法,让 app 最多有 10 分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。

让程序在后台长久运行的示例代码如下:

// 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;}
0 0
原创粉丝点击