关于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 转载声明: 本译文已授权开发者头条享有独家转 ...
随机推荐
- whil
while true; do select input in cpu_load disk_load disk_use disk_inode mem_use tcp_status cpu_top10 m ...
- MJRefresh在Xode6中报错处理
MJRefresh在Xcode6中会报错,objc_msgSend(self.beginRefreshingTaget, self.beginRefreshingAction, self),简单调 ...
- vs关于“当前不会命中断点 还没有为该文档加载任何符号”的解决方法
首先调式的时候确定在debug模式下, 解决方法:工具-选项-调试 -(启用“仅我的代码”)勾去掉.
- Python全栈开发记录_第四篇(集合、函数等知识点)
知识点1:深拷贝和浅拷贝 非拷贝(=赋值:数据完全共享,内存地址一样,修改一个另一个也变化) 浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层)像[[1,2],3,4]如果修改列表中列 ...
- java 日志脱敏框架 sensitive-新版本0.0.2-深度拷贝,属性为对象和集合的支持
项目介绍 日志脱敏是常见的安全需求.普通的基于工具类方法的方式,对代码的入侵性太强.编写起来又特别麻烦. 本项目提供基于注解的方式,并且内置了常见的脱敏方式,便于开发. 用户也可以基于自己的实际需要, ...
- start to use await
import { browser, $, $$, by, element, protractor } from "protractor"; //import { SearchPag ...
- Python12(接口继承,子类调用父类,多态)
接口继承: 基类不用实现内部逻辑,只是为了规范子类,可以用abc模块中以添加装饰器的方式实现 import abc class All_file(metaclass=abc.ABCMeta): @ab ...
- 运用node真机调试移动web项目
很多时候我们对移动端进行测试的时候,有pc端的测试,也有真机上的测试,pc的测试就不多说了,因为其实基本上大家都懂的.真机测试上也有几种方法,这里就推荐三种: 移动端真机调试方法 chrome真机调试 ...
- 基于C/S 结构的IM即时通讯软件--上篇
目的:实现类似QQ群聊的聊天室,可以看到好友列表及互相传送信息. 分析:可基于C/S结构实现即时通讯 1.创建基于对话框的MFC程序(支持windows套接字),并增加相应的类与结构体,完善对话框界面 ...
- 关于Qrc文件的用法
在python文件xxx.py中调用资源文件,一般来说,需要将资源放在xxx.py的相同目录下:然而,当在xxx.py下建立一个统一目录/rec则需要建立xxx.qrc文件才能让xxx.py调用,调用 ...