为什么一定要在主线程刷新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);
}

  

执行结果:

 
333.gif

结果分析:
从图中点击按钮后,虽然任务是在同一个子线程执行,但是并没有按顺序执行,而是首先立即执行NSLog日志输出,但是接下来并没有执行刷新按钮标题,和新建按钮的代码,而是优先执行sleep(5)延迟代码,然后才执行的刷新和新建控件的代码

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
转自简书
作者:wg刚
链接:https://www.jianshu.com/p/8d0aa880d55b
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

关于iOS刷新UI需要在主线程执行的更多相关文章

  1. WPF里面多线程访问UI线程、主线程的控件

    如果出现以下错误:调用线程无法访问此对象,因为另一个线程拥有该对象. 你就碰到多线程访问UI线程.主线程的控件的问题了. 先占位.

  2. iOS开发之GCD同步主线程、异步主线程

    /** 在主线程执行block */ + (void)gs_synExecuteOnMainThread:(void (^)(void))block { if ((nil == block) || ( ...

  3. iOS 安全地在主线程执行一个Block

    //主线程同步队列 #define dispatch_main_sync_safe(block)\ if ([NSThread isMainThread]) {\ block();\ } else { ...

  4. 在Qt中将函数发送到主线程执行

    考虑这样一种需求,使用Qt的线程类QThread在后台执行操作(比如说拷贝文件)的时候发生了错误,产生了一个错误信息需要提醒给用户,在后台输出很显然是不够的,因为用户可能根据就没有任何控制台可供程序输 ...

  5. 主线程中也不绝对安全的 UI 操作

    从最初开始学习 iOS 的时候,我们就被告知 UI 操作一定要放在主线程进行.这是因为 UIKit 的方法不是线程安全的,保证线程安全需要极大的开销.那么问题来了,在主线程中进行 UI 操作一定是安全 ...

  6. Android子线程更新UI主线程方法之Handler

    背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. ...

  7. 03_主线程联网问题&ANR&子线程不能修改UI

    如果不使用HAXM,恐怕网页源码查看器无法获取servlet的源码.初步猜测是安卓模拟器运行速度太慢了.如果CPU不支持VT-x的话,HAXM是安装不上的.所以可以先开启VT-x. 可以参考几篇文章h ...

  8. Android关于主线程和非主线程

    必须在主线程执行的任务: (1)UI更新 必须在非主线程中执行的任务 (1)Http请求 如执行:ImageHelper.getInstance().loadImageSync(picUrl); 外面 ...

  9. RxJava开发精要7 – Schedulers-解决Android主线程问题

    原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...

随机推荐

  1. 搭建Mock Server

    1.为什么要搭建mock-server? 为了更好的分工合作,让前端能在不依赖后端环境的情况下进行开发,其中一种手段就是为前端开发者提供一个 web 容器,这个本地环境就是 mock-server. ...

  2. centos7 系统优化脚本

    脚本一: #!/usr/bin/env bash #设置环境变量 export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sb ...

  3. (转)K-近邻算法(KNN)

    K-近邻算法(KNN)概述  KNN是通过测量不同特征值之间的距离进行分类.它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别 ...

  4. Java笔记Spring(六)

    web.xml各节点加载顺序 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns=&q ...

  5. 学习Xen

    先找到两个大佬博客 进行学习 http://www.cnblogs.com/BloodAndBone/archive/2010/11/02/1866907.html https://www.cnblo ...

  6. js实现点击按钮复制文本功能

    最近项目活动中用到复制文本功能,发现在chrome中之前的clipboard的demo失效了,查了下发现是因为版本升级导致的.最新用法如下: <!DOCTYPE html> <htm ...

  7. SVN忽略已提交的文件(ignore,移出版本控制)

    本文适用于已安装TortoiseSVN客户端的同学. 1.右键点击要忽略的文件夹或文件,鼠标移到“TortoiseSVN”,找到“Unversion and add to ignore list”,选 ...

  8. Django基础模型层(77-78)

    jango框架之模型层(d77-78)一 单表操作: 1 mysql数据库:settings里配置  'default': {   # key值必须都是大写   'ENGINE': 'django.d ...

  9. thinkphp5 部署注意事项

    配置tp5 需要修改设置 1. 通过yum安装的Apache,会默认安装在/etc/httpd因此配置文件也在相应的目录中 修改文件vim /etc/httpd/conf/httpd.confhttp ...

  10. 强大的oracle分析函数

    转载:https://www.cnblogs.com/benio/archive/2011/06/01/2066106.html 学习步骤:1. 拥有Oracle EBS demo 环境 或者 PRO ...