iOS-GCD处理后台线程和UI线程的交互
一个例子:
在iPhone上做一个下载网页的功能,就是:在iPhone上放一个按钮,单击按钮时,显示一个转动的圆圈,表示正在进行下载,下载完成后,将内容加载到界面上的一个文本控件上。
使用GCD前:
static NSOperationQueue *queue;
// 按钮的点击事件
-(void)someClick:(id)sender{
self.indicator.hidden = NO;
[self.indicator startAnimating];
queue = [NSOperationQueue alloc]init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];
[queue addOperation:op];
}
-(void)download{
NSURL *url = [NSURL URLWithString:@"http://www.youdao.com"];
NSError *error;
NSString *data = [NSString stringWithContentOfURL:url encoding:NSUTF8StringEncoding error:&error];
if(data !=nil){
[self performSelectorOnMainThread:@selector(download_complexted:) withObject:data waitUntilDone:NO];
}else{
NSLog(@"%@",error);
}
}
-(void)download_complexted:(NSString *)data{
[self.indicator stopAnimating];
self.indicator.hidden = YES;
self.content.text = data;
}
使用GCD以前分成了三部分来写。
使用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 stringWithContentOfURL:url encoding:NSUTF8StringEncoding error:&error];
if(data !=nil){
dispatch_async(diapatch_get_main_queue(),^{
[self.indicator stopAnimating];
self.indicator.hidden = YES;
self.content.text = data;
});
}else{
NSLog(@"%@",error);
}
});
首先,看到代码变短了,变清楚了。
系统提供的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
dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL);
dispatch_async(urls_queue, ^{
// your code
});
dispatch_release(urls_queue);
另外,GCD还有一些高级用法,例如让后台两个线程并行执行,然后等两个线程都结束后,再汇总执行结果。这个可以用dispatch_group_t、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引用在外部即可。
后台的运行:
在appdelegate.h
@property (assign,nonatomic)UIBackgroundTaskIdentifier backgroundUpdateTask;
在appdelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self beginBackgroundUpdateTask];
//在这里加上你需要长久运行的代码
[self endBackgroundUpdateTask];
}
-(void)beginBackgroundUpdateTask{
self.backgroundUpdateTask = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
-(void)endBackgroundUpdateTask{
[[UIApplication sharedApplication]endBackgroundTask:self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
iOS-GCD处理后台线程和UI线程的交互的更多相关文章
- 新建线程与UI线程间的通信
现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...
- [Android学习笔记]子线程更新UI线程方法之Handler
关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...
- OkHttp3几个简单的例子和在子线程更新UI线程的方法
okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...
- C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它
C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...
- C#中后台线程和UI线程的交互
在C#中,从Main()方法开始一个默认的线程,一般称之为主线程,如果在这个进行一些非常耗CPU的计算,那么UI界面就会被挂起而处于假死状态,也就是说无法和用户进行交互了,特别是要用类似进度条来实时显 ...
- Android ActivityThread(主线程或UI线程)简介
1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...
- WPF线程获取UI线程
WPF中只能是UI线程才可以改变UI控件相关,当采用多线程工作时,可用以下代码获取 UI线程进行操作: App.Current.Dispatcher.Invoke((Action)delegate() ...
- C#用副线程改主线程(UI线程)的控件属性的方法(包括Winform和WPF)
C#用副线程去试图修改主线程的UI控件会报出异常,解决方案是使用副线程注册事件通知主线程自己去修改UI控件 在winform中,方法如下 private void button1_Click(obje ...
- 主线程与UI线程简介
---------------siwuxie095 Java 程序的主线程 当 Java 程序启动时,一个线程立刻运行,该线程通常叫做程 ...
- C#在非UI线程调用UI线程的控件
首先需要定义一个委托(delegate): private delegate void delegateSetProcessBarVal(int value); 然后定义一个方法来执行具体的操作: p ...
随机推荐
- FreeMarker生成word
FreeMarker生成word数据填充是通过,Map填充. Map dataMap = new HashMap<String, Object>(); List<User> l ...
- bzoj3097 hash killer 1——构造题
题意 在 $u64$ 自然溢出下,请输出一串字符串和 $L$,使得对任意 $Base$ 都能找到两个长度为 $L$ 的字串的 $Hash$ 值相同. 分析 $u64$ 自然溢出等价于两个哈希值模 $2 ...
- mybatis自测错题总结
试题分析:MyBatis有两种事务管理器类型是JDBC和MANAGED 试题分析:mybatis-config.xml文件使用用来编写影响mybatis行为的设置(settings) 和属性(pe ...
- 使用jQuery快速高效制作网页交互特效--初始jQuery
一. jQuery基本概念介绍 1.1 什么是jQuery一个javascript库,把常用方法写到一个js文件中,需要的时候直接调用即可学习jQuery就是学习一些方法 ...
- VIM--保存和退出等命令
在 Linux 中使用 vim 时,输入 vim xxx.file 按 ESC,左下角就可以进行输入 :w 保存但不退出 :wq 保存并退出 :q 退出 :q! 强制退出,不保存 :e! 放弃所有修改 ...
- 第一章使用JSP/Server技术开发新闻发布系统第一章动态网页开发基础
一:为什么需要动态网页 由于静态网页的内容是固定的,不能提供个性化和定制化得服务,使用动态网页可真正地与用户实现互动. 二:什么是动态网页 ①:动态网页是指在服务器端运行的,使用程序语言设 ...
- Oracle数据库限定特定用户 特定IP 登录
不允许test用户在 192.168.1.3 机器上访问数据库. 两种写法. 1 CREATE OR REPLACE TRIGGER DOPR AFTER LOGON ON test.schema B ...
- 二十二. 安装部署Tomcat服务器、使用Tomcat部署虚拟主机、使用Varnish加速Web
web proxy web1 web2 1.安装部署Tomcat服务器 web1 1.1 使用RPM安装JDK环境 ]# yum -y install java-1.8.0-openjdk ]# ...
- 理解 __declspec
“__declspec”是Microsoft c++中专用的关键字,它配合着一些属性可以对标准C++进行扩充.这些属性有:align.allocate.deprecated. dllexport.dl ...
- Educational Codeforces Round 74
目录 Contest Info Solutions A. Prime Subtraction B. Kill 'Em All C. Standard Free2play D. AB-string E. ...