Runloop的使用
系统为我们提供了多种模式,下面列一些比较常遇到的:
kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。
UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。
UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。
NSRunLoopCommonModes: 包含了多种模式:default, modal, 和tracking modes。
runloop 和线程的关系:
1 run oop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分
2 一条线程对应一个RunLoop对象,每条线程都有唯一一个与之对应的RunLoop对象。
3 我们只能在当前线程中操作当前线程的RunLoop,而不能去操作其他线程的RunLoop。
4 RunLoop对象在第一次获取RunLoop时创建,销毁则是在线程结束的时候。
5 主线程的RunLoop对象系统自动帮助我们创建好了(原理如下),而子线程的RunLoop对象需要我们主动创建。
使用:
1、NSTimer的创建使用
当实例化NSTimer对象的时候,通常会使用 scheduledTimerWithTimeInterval 方法。该方法会自动为我们实例化的timer添加到当前线程的RunLoop中,并且默认模式是 NSDefaultRunLoopMode。但当前线程是主线程时,某些UI事件,比如ScrollView正在拖动,将会RunLoop切换成 NSEventTrackingRunLoopMode 模式,在这个模式下,默认的 NSDefaultRunLoopMode 模式中注册的事件是不会执行的。也就是说,使用 scheduledTimerWithTimeInterval 方法添加到RunLoop中的Timer就不会执行。
为了设置一个不被UI干扰的Timer,我们需要手动创建一个Timer,然后使用RunLoop的 addTimer:forMode: 方法来把Timer按照指定的模式加入到RunLoop中。这里使用 NSRunLoopCommonModes 模式,这个模式相当于 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode 的结合。
2 ImageView推迟显示
一些动画执行过程中,
或者scrllview滑动过程汇总image的显示
[cell performSelector:@selector(setImage)withObject:nil afterDelay:0 inModes:@[NSDefaultRunLoopMode]];
[imageview performSelector: inModes: ]
3 后台常驻线程(很常用)
我们在开发应用程序的过程中,如果后台操作特别频繁,经常会在子线程做一些耗时操作(下载文件、后台播放音乐等),我们最好能让这条线程永远常驻内存。
那么怎么做呢?
添加一条用于常驻内存的强引用的子线程,在该线程的RunLoop下添加一个Sources,开启RunLoop。
具体实现过程如下:
在项目的ViewController.m中添加一条强引用的thread线程属性,如下图:
在viewDidLoad中创建线程self.thread,使线程启动并执行run1方法,代码如下。在Demo中,请在viewDidLoad调用[self showDemo4];方法。
运行之后发现打印了----run1-----,而未开启RunLoop则未打印。
这时,我们就开启了一条常驻线程,下边我们来试着添加其他任务,除了之前创建的时候调用了run1方法,我们另外在点击的时候调用run2方法。
那么,我们在touchesBegan中调用PerformSelector,从而实现在点击屏幕的时候调用run2方法。具体代码如下:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ //利用performSelector,在self.thread的线程中调用run2方法执行任务
[self performSelector:@selector(run2)onThread:self.thread withObject:nil waitUntilDone:NO];
}
-(void)run2
{
NSLog(@"----run2------");
}
经过运行测试,除了之前打印的----run1-----,每当我们点击屏幕,都能调用----run2------。
这样我们就实现了常驻线程的需求。
最新文章
- 利用Select2优化@Html.ListBoxFor显示,学会用MultiSelectList
- Android Sudoku第一版
- C++ inline
- DOJO 如何清空表单
- Java垃圾回收器
- Runtime 实现 动态添加属性
- Linux安装JDK详细步骤
- Java中“|”和“||”用法的区别
- ubuntu 安装python,easy_install和pip
- pomelo 协议
- [js高手之路]Node.js模板引擎教程-jade速学与实战3-mixin
- es6零基础学习之构建脚本(二)
- 【RL-TCPnet网络教程】第41章 HTTP超文本传输协议基础知识
- (hdu) 4857 逃生 (拓扑排序+优先队列)
- load加载层-layui
- MAC使用pycharm上传代码到Github上
- hdu 1864 最大报销额 01背包
- 基于Redis的Spring cache 缓存介绍
- Win10家庭版无法远程桌面连接的解决方法
- Alpha 冲刺二
热门文章
- springboot项目中使用shiro实现用户登录以及权限的验证
- python学习笔记---流程控制
- 4.httprunner-参数化和数据驱动
- 二、.Net Core搭建Ocelot
- 第2-1-4章 SpringBoot整合FastDFS文件存储服务
- 这次,听人大教授讲讲分布式数据库的多级一致性|TDSQL 关键技术突破
- Java新特性(2):Java 10以后
- 深度解析KubeEdge EdgeMesh 高可用架构
- (GCC) gcc 编译选项 -fno-omit-frame-pointer,-fno-tree-vectorize,fno-optimize-sibling-calls;及内存泄漏、非法访问检测 ASAN
- 使用c#的 async/await编写 长时间运行的基于代码的工作流的 持久任务框架