关于iOS刷新UI需要在主线程执行
为什么一定要在主线程刷新UI?
安全+效率:因为UIKit框架不是线程安全的框架,当在多个线程进行UI操作,有可能出现资源抢夺,导致问题。
其实:在子线程是不能更新UI的, 看到能更新的结果只是个假象。因为:在子线程代码完成之后,回到主线程,然后执行了子线程的更新UI的代码,由于这个时间很短,所以看起来是能够在子线程刷新UI的。想验证的话也很简单,看下面demo:点击按钮,会开启一个子线程,然后在子线程中刷新该按钮的标题,再新建一个按钮,最后一行代码是延迟5秒。
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.button];
}
-(UIButton *)button{
if (!_button) {
_button = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, SCREEN_WIDTH, 100)];
_button.backgroundColor = [UIColor yellowColor];
[_button addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
[_button setTitle:@"UI" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
_button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
_button.titleLabel.font = [UIFont systemFontOfSize:13];
}
return _button;
}
- (void)btnClicked {
[NSThread detachNewThreadSelector:@selector(uiRefreashTest) toTarget:self withObject:nil];
}
- (void)uiRefreashTest {
NSLog(@"当前线程:%@", [NSThread currentThread]);
NSLog(@"主线程:%@", [NSThread mainThread]);
//在子线程刷新该按钮的标题名字为子线程信息
NSString *subStr = [NSString stringWithFormat:@"子线程:%@", [NSThread currentThread]];
NSString *mainStr = [NSString stringWithFormat:@"主线程:%@", [NSThread mainThread]];
[_button setTitle:subStr forState:UIControlStateNormal];
CGRect labelTitleSize = [subStr boundingRectWithSize:CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil];
_button.frame = CGRectMake(0, 100, labelTitleSize.size.width+10, labelTitleSize.size.height+10);
//在子线程新建一个按钮,标题名字为主线程信息
UIButton *newBtn = [[UIButton alloc] init];
newBtn.backgroundColor = [UIColor greenColor];
newBtn.titleLabel.font = [UIFont systemFontOfSize:13];
newBtn.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[newBtn setTitle:mainStr forState:UIControlStateNormal];
[newBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
CGRect labelTitleSize01 = [mainStr boundingRectWithSize:CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil];
newBtn.frame = CGRectMake(0, 250, labelTitleSize01.size.width+10, labelTitleSize01.size.height+10);
[self.view addSubview:newBtn];
//在这个子线程延迟5秒钟
sleep(5);
}
执行结果:

结果分析:
从图中点击按钮后,虽然任务是在同一个子线程执行,但是并没有按顺序执行,而是首先立即执行NSLog日志输出,但是接下来并没有执行刷新按钮标题,和新建按钮的代码,而是优先执行sleep(5)延迟代码,然后才执行的刷新和新建控件的代码
链接:https://www.jianshu.com/p/8d0aa880d55b
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
关于iOS刷新UI需要在主线程执行的更多相关文章
- WPF里面多线程访问UI线程、主线程的控件
如果出现以下错误:调用线程无法访问此对象,因为另一个线程拥有该对象. 你就碰到多线程访问UI线程.主线程的控件的问题了. 先占位.
- iOS开发之GCD同步主线程、异步主线程
/** 在主线程执行block */ + (void)gs_synExecuteOnMainThread:(void (^)(void))block { if ((nil == block) || ( ...
- iOS 安全地在主线程执行一个Block
//主线程同步队列 #define dispatch_main_sync_safe(block)\ if ([NSThread isMainThread]) {\ block();\ } else { ...
- 在Qt中将函数发送到主线程执行
考虑这样一种需求,使用Qt的线程类QThread在后台执行操作(比如说拷贝文件)的时候发生了错误,产生了一个错误信息需要提醒给用户,在后台输出很显然是不够的,因为用户可能根据就没有任何控制台可供程序输 ...
- 主线程中也不绝对安全的 UI 操作
从最初开始学习 iOS 的时候,我们就被告知 UI 操作一定要放在主线程进行.这是因为 UIKit 的方法不是线程安全的,保证线程安全需要极大的开销.那么问题来了,在主线程中进行 UI 操作一定是安全 ...
- Android子线程更新UI主线程方法之Handler
背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. ...
- 03_主线程联网问题&ANR&子线程不能修改UI
如果不使用HAXM,恐怕网页源码查看器无法获取servlet的源码.初步猜测是安卓模拟器运行速度太慢了.如果CPU不支持VT-x的话,HAXM是安装不上的.所以可以先开启VT-x. 可以参考几篇文章h ...
- Android关于主线程和非主线程
必须在主线程执行的任务: (1)UI更新 必须在非主线程中执行的任务 (1)Http请求 如执行:ImageHelper.getInstance().loadImageSync(picUrl); 外面 ...
- RxJava开发精要7 – Schedulers-解决Android主线程问题
原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...
随机推荐
- 搭建Mock Server
1.为什么要搭建mock-server? 为了更好的分工合作,让前端能在不依赖后端环境的情况下进行开发,其中一种手段就是为前端开发者提供一个 web 容器,这个本地环境就是 mock-server. ...
- centos7 系统优化脚本
脚本一: #!/usr/bin/env bash #设置环境变量 export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sb ...
- (转)K-近邻算法(KNN)
K-近邻算法(KNN)概述 KNN是通过测量不同特征值之间的距离进行分类.它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别 ...
- Java笔记Spring(六)
web.xml各节点加载顺序 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns=&q ...
- 学习Xen
先找到两个大佬博客 进行学习 http://www.cnblogs.com/BloodAndBone/archive/2010/11/02/1866907.html https://www.cnblo ...
- js实现点击按钮复制文本功能
最近项目活动中用到复制文本功能,发现在chrome中之前的clipboard的demo失效了,查了下发现是因为版本升级导致的.最新用法如下: <!DOCTYPE html> <htm ...
- SVN忽略已提交的文件(ignore,移出版本控制)
本文适用于已安装TortoiseSVN客户端的同学. 1.右键点击要忽略的文件夹或文件,鼠标移到“TortoiseSVN”,找到“Unversion and add to ignore list”,选 ...
- Django基础模型层(77-78)
jango框架之模型层(d77-78)一 单表操作: 1 mysql数据库:settings里配置 'default': { # key值必须都是大写 'ENGINE': 'django.d ...
- thinkphp5 部署注意事项
配置tp5 需要修改设置 1. 通过yum安装的Apache,会默认安装在/etc/httpd因此配置文件也在相应的目录中 修改文件vim /etc/httpd/conf/httpd.confhttp ...
- 强大的oracle分析函数
转载:https://www.cnblogs.com/benio/archive/2011/06/01/2066106.html 学习步骤:1. 拥有Oracle EBS demo 环境 或者 PRO ...