GCD--自己的开发笔记
来源:互联网 发布:晨光麦事件 知乎 编辑:程序博客网 时间:2024/06/08 16:52
GCD
在object-c 和swift GCD语言都适用
例:
// 原代码块一self.indicator.hidden = NO;[self.indicator startAnimating];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 原代码块二 NSURL * url = [NSURL URLWithString:@"http://www.youdao.com"]; NSError * error; NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; if (data != nil) { // 原代码块三 dispatch_async(dispatch_get_main_queue(), ^{ [self.indicator stopAnimating]; self.indicator.hidden = YES; self.content.text = data; }); } else { NSLog(@"error when download:%@", error); }});
一、block的定义
block的定义有点象函数指针,差别是用 ^ 替代了函数指针的 * 号,如下所示:
// 申明变量 (void) (^loggerBlock)(void); // 定义 loggerBlock = ^{ NSLog(@"Hello world"); }; // 调用 loggerBlock();大多数时候,我们通常使用内联的方式来定义block,即将它的程序块写在调用的函数里面,例如这样:
dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something });
二、系统提供的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), ^{ // 汇总结果 });
// 根据url获取UIImage - (UIImage *)imageWithURLString:(NSString *)urlString { NSURL *url = [NSURL URLWithString:urlString]; NSData *data = [NSData dataWithContentsOfURL:url]; // 这里并没有自动释放UIImage对象 return [[UIImage alloc] initWithData:data]; } - (void)downloadImages { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 异步下载图片 dispatch_async(queue, ^{ // 创建一个组 dispatch_group_t group = dispatch_group_create(); __block UIImage *image1 = nil; __block UIImage *image2 = nil; // 关联一个任务到group dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 下载第一张图片 NSString *url1 = @"http://car0.autoimg.cn/upload/spec/9579/u_20120110174805627264.jpg"; image1 = [self imageWithURLString:url1]; }); // 关联一个任务到group dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 下载第一张图片 NSString *url2 = @"http://hiphotos.baidu.com/lvpics/pic/item/3a86813d1fa41768bba16746.jpg"; image2 = [self imageWithURLString:url2]; }); // 等待组中的任务执行完毕,回到主线程执行block回调 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ self.imageView1.image = image1; self.imageView2.image = image2; // 千万不要在异步线程中自动释放UIImage,因为当异步线程结束,异步线程的自动释放池也会被销毁,那么UIImage也会被销毁 // 在这里释放图片资源 [image1 release]; [image2 release]; }); // 释放group dispatch_release(group); }); }
三、修改block之外的变量
默认情况下,在程序块中访问的外部变量是复制过去的,即写操作不对原变量生效。但是你可以加上 __block来让其写操作生效,示例代码如下:__block int a = 0; void (^foo)(void) = ^{ a = 1; } foo(); // 这里,a的值被修改为1
四、暂停、继续queue
我们可以使用dispatch_suspend函数暂停一个queue以阻止它执行block对象;
使用dispatch_resume函数继续dispatch queue。
调用dispatch_suspend会增加queue的引用计数,调用dispatch_resume则减少queue的引用计数。
当引用计数大于0时,queue就保持挂起状态。因此你必须对应地调用suspend和resume函数。
挂起和继续是异步的,而且只在执行block之间(比如在执行一个新的block之前或之后)生效。挂起一个queue不会导致正在执行的block停止。
五、后台运行
使用block的另一个用处是可以让程序在后台较长久的运行。在以前,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是应用可以调用UIApplication的beginBackgroundTaskWithExpirationHandler
方法,让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;}
总体来说,GCD能够极大地方便开发者进行多线程编程。个人现在都没有怎么用代理了,都用block了。
0 0
- GCD--自己的开发笔记
- GCD开发笔记(二):GCD的使用
- 自己的开发笔记
- iOS开发笔记>> GCD调度组的使用
- 苹果开发 笔记(50)GCD
- 关于GCD的学习笔记
- iOS开发:GCD的理解
- iOS开发:GCD的使用
- GCD笔记
- GCD 笔记
- GCD笔记
- GCD笔记
- GCD笔记
- iOS开发笔记--调用打开AppStore显示自己的App
- IOS开发笔记之自己遇到的问题
- iOS开发笔记--调用打开AppStore显示自己的App
- nginx学习笔记一(开发自己的http模块)
- GCD,线程使用的一些笔记
- linux环境下安装PHP中间件ICE(三)
- Jetty开发指导:Maven和Jetty
- 用实验方法加深理解Oracle的外连接(left/right/full)和内连接(inner)
- linux环境下编译安装ICE
- poj 1321
- GCD--自己的开发笔记
- ARC和非ARC混编
- 计算机视觉领域的一些牛人博客,研究机构等的网站链接
- iOS围绕某点缩放或旋转的AnchorPoint的设定
- 索引数组冒泡方法
- PHP中间件--ICE
- 配置Nginx前端Apache后端服务器LNMPA-与LNMP,HHVM性能比拼
- 灌水VS抽水
- Eclipse安装Marketplace Client