GCD的使用
来源:互联网 发布:高清网络播放器排名 编辑:程序博客网 时间:2024/06/01 18:20
一. GCD 是Grand Central Dispatch 的缩写
GCD是Apple开发的一个多核编程的解决方法。GCD是一个代替NSThread,NSOperator技术的高效和强大的技术。
GCD 和block 的配合使用,可以方便的进行多线程编程。
二.应用举例
让我们啦看一个编程场景。我们在iPhone上做一个下载的功能,该功能非常简单,就是在iPhone上放置一个按钮,当我们点击按钮的时候开始惊进行下载,下载完成之后,件内容显示在控件上面。
三.不用GCD前
虽然功能简单,但是我们必须把下载过程放到后台线程中,否则会阻塞UI线程显示。所以,如果不用GCD,我们需要些如下3个方法:
(1). someClick 方法是点击按钮后的代码,我么可以看到我们用NSInvocationOperation 建立一个后台线程,并且放到NSOperationQueue 中。后台线程执行downLoad方法。
(2).download方法处理下载网页的逻辑。下载完成后调用performSelectorOnMainThread执行download_completed 方法。
(3).download_completed 进行clear up的工作,并把下载的内容显示到文本控件上来。
这3个方法的代码如下。可以看到,虽然开始下载——》下载中——》下载完后这3个步骤是整个功能的三步。但是他们却被切分成3块,他们之间是3个方法,所以还需要传递数据参数,另外,下载可能放到Model的类中来做,而界面的控制放到ViewController层来做,这使得本来就分开的代码变得更加散落。代码的可读性大大降低。
static NSOperationQueue *queue;
-(IBAction)someClick:(id)sender
{
self.indicator.hidden=no;
[self.indicator startAnimating];
queue=[[NSOperatorQueue alloc]]init];
NSInvocationOperation *op=[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downLoad) object:nil] autorelease];
[queue addOperation:op];
}
-(void)downLoad
{
NSURL *url=[NSURLURLWithString:@"http://www.youdao.com"];
NSError *error;
NSString *data=[NSStringstringWithContentsOfURL:url encoding:NSUTF8StringEncodingerror:&error];
if(data!=nil){
[selfperformSelectorOnMainThread:@selector(downLoad_complement:)withObject:data waitUntilDone:NO];
}else{
NSLog(@"error when download:%@", error);
}
}
-(void)downLoad_complement:(NSString *)data
{
NSLog(@"call back");
[self.indicator stopAnimating];
self.indicator.hidden =YES;
self.content.text = data;
NSLog(@"==data=%@",data);
}
使用GCD后,以上的3个方法都可以放到一起,如下所示
//代码块1
self.indicator.hidden=no;
[self.indicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
//代码块2
NSURL *url=[NSURLURLWithString:@"http://www.youdao.com"];
NSError *error;
NSString *data=[NSStringstringWithContentsOfURL:url encoding:NSUTF8StringEncodingerror:&error];
if(data!=nil){
//代码会3
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];
self.indicator.hidden =YES;
self.content.text=data;
NSLog(@"===data==%@",data);
});
}else{
NSLog(@"error when download:%@", error);
}
});
首先我们可以看到,代码变短了。因为少了原来 3 个方法的定义,也少了相互之间需要传递的变量的封装。
另外,代码变清楚了,虽然是异步的代码,但是它们被 GCD合理的整合在一起,逻辑非常清晰。如果应用上 MVC 模式,我们也可以将 View Controller 层的回调函数用 GCD的方式传递给 Modal 层,这相比以前用@selector 的方式,代码的逻辑关系会更加清楚。
block的定义
dispatch_async(dispatch_get_global_queue(0,0),^{
// someThing
});
从上面大家可以看出,block有如下特点:
1.程序块可以再代码中以内联的方式定义。
2.程序块可以访问在创建他的范围内的可用变量。
系统提供的 dispatch 方法
为了方便地使用 GCD,苹果提供了一些方法方便我们将 block放在主线程 或后台线程执行,或者延后执行。使用的例子如下:
后台执行
dispatch_async(dispatch_get_global_queue(0,0),^{
//something
});
//主线程执行:
dispatch_async(dispatch_get_main_queue(), ^{
//something
});
//一次性执行
staticdispatch_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);
dispatch_after(popTime,dispatch_get_main_queue(), ^{
//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_group_t group=dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
//并行执行的线程一
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
//并行执行的线程二
});
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
//汇总结果
});
// 修改 block之外的变量
// 默认情况下,在程序块中访问的外部变量是复制过去的,即写操作不对原变量生效。但是你可以加上 __block来让其写操作生效,示例代码如下:
__blockint a=0;
void (^foo)(void)=^{
a=1;
};
foo();
// 这里,a的值被修改为1
//使用 block的另一个用处是可以让程序在后台较长久的运行。在以前,当 app 被按 home 键退出后,app仅有最多 5 秒钟的时候做一些保存或清理资源的工作。但是应用可以调用 UIApplication的beginBackgroundTaskWithExpirationHandler方法,让 app最多有 10 分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。
// 让程序在后台长久运行的示例代码如下
在APPDelegate.h 文件中@property (nonatomic,assign)UIBackgroundTaskIdentifier backgroundUpdateTask;
AppDelegate.m 文件中
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self beingBackgroundUpdateTask];
//在这里加上你需要长久运行的代码
[selfendBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask
{
self.backgroundUpdateTask = [[UIApplicationsharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[selfendBackgroundUpdateTask];
}];
}
- (void)endBackgroundUpdateTask
{
[[UIApplicationsharedApplication] endBackgroundTask:self.backgroundUpdateTask];
self.backgroundUpdateTask =UIBackgroundTaskInvalid;
}
大家尽量的使用GCD 蜡处理后台线程和UI线程的交互。
- 多线程GCD的使用
- GCD的使用.
- GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- iOS GCD的使用
- GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- GCD的使用
- 多线程GCD的使用
- GCD的使用
- 多线程GCD的使用
- gcd的使用
- GCD的简单使用
- GCD的基本使用
- GCD的使用
- UNITY 5.1.4 发行说明 中文版
- HDU - 2102 A计划(dfs)
- 学习笔记——冒泡排序
- ADF:获取下拉框的值
- 用WASAPI实现windows PC系统声音捕获
- GCD的使用
- 一步步调通Openfire3.10.2+Smack4.1.4官方Demo
- linux下搭建ftp服务器
- Java学习笔记(二)GUI组件(1)
- 黑马程序员-OC类的声明和实现,以及OC的优势
- Android系列---JSON数据解析
- EF(3)-Linq TO ADO.NET
- UNITY 5.2.1 发行说明 中文版
- C#中out和ref之间的区别