NSRunLoop学习笔记
2016-03-09 09:38
302 查看
内容是自己学习笔记,来源于互联网
处理APP的各种事件:触摸,定时器,selector事件,事件触发的时候,runLoop会按步骤执行事件。
节省CPU的资源,提升程序性能,合理分配工作和休眠时间,在没有操作任务的时候会进入休眠,有任务到来会唤醒.
Foundation -> NSRunLoop
Core Foundation -> CFRunLoopRef
NSRunLoop和CFRunLoopRef都代表RunLoop对象。NSRunLoop是基于CFRunLoopRef的一层OC的包装,CFRunLoopRef是RunLoop底层API.
主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
RunLoop 在第一次获取时候创建,在线程结束时候销毁.
CFRunLoopRef
一个RunLoop可以包含若干个Mode,一个Mode 包含不同的若干个source,timer,observer。
每次RunLoop启动只能指定其中一种模式,可以通过curreMode方法获取
切换mode只能退出Loop,重新再指定一个Mode进入,这样可以分开不同模式下的source,timer,observer
CFRunLoopModeRef以供有5个,其中有两个用不到一个是UIInitializationRunLoopMode 是刚刚进入程序的时候进入的第一个,启动完成后就退出了,还有一个GSEventReceiveRunLoopMode,是系统内部的,也用不到,而且代码根本打不出来,所以可以忽略.
分类1:
- Port-Based Source 基于端口的,内核或者其他线程发过来的信息
- Custom Input Source 自定义的,一般不用
- Cocoa perform selector sources 通过selector消息选择器发送的事件
分类2:
- source0 :非基于port的
- source1 :基于内核的和其他线程通信,接受分发系统事件.
网络版本
第一种:
第二种:创建一个纯净的定时器,需要自己手动设置运行模式
可以解决tableView或者scrollView滑动时候卡顿问题,让图片仅仅在不滑动的时候加载.提升用户体验.
实现策略:
创建一个线程:
在线程的run方法里面,添加代码启动新创建的线程的runLoop,
runLoop的run方法,运行的时候如果发现运行模式为空会直接退出,
runLoop不可以没有source,timer,observer.如果3个都没有,就会退出.
所以必须要添加一个保证不退出。
调用run方法相当下面的情况的一种,都是一致运行到一个非常大的日期,保证不会退出.创造一个死循环.
runLoop循环,不会像do while循环卡死,而是一致在不断的运行着,只有当事件触发的时候才会响应时间,没有事件就会休眠.
RunLoop简介
基本作用
保持程序的持续运行,相当于一个do while循环,程序相当于一个死循环,一直在循环内做事情。程序启动时已经启动了一个runLoop,所以程序不会直接退出。是在main函数启动的,和主线程相关.处理APP的各种事件:触摸,定时器,selector事件,事件触发的时候,runLoop会按步骤执行事件。
节省CPU的资源,提升程序性能,合理分配工作和休眠时间,在没有操作任务的时候会进入休眠,有任务到来会唤醒.
runLoop对象
iOS 两套方案访问runLoopFoundation -> NSRunLoop
Core Foundation -> CFRunLoopRef
NSRunLoop和CFRunLoopRef都代表RunLoop对象。NSRunLoop是基于CFRunLoopRef的一层OC的包装,CFRunLoopRef是RunLoop底层API.
RunLoop与线程的关系
每条线程都有唯一的一个与之对应的RunLoop对象.主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
RunLoop 在第一次获取时候创建,在线程结束时候销毁.
获取RunLoop对象的方法
Foundation[NSRunLoop mainRunLoop]; [NSRunLoop currentRunLoop];
CFRunLoopRef
CFRunLoopGetCurrent(); CFRunLoopGetMain();
RunLoop相关类
CFRunLoopRef ;// CFRunLoopSourceRef;//source CFRunLoopTimerRef;//定时器 CFRunLoopObserverRef;//观察者 CFRunLoopModeRef;//这个类没有外漏
CFRunLoopModeRef
CFRunLoopModeRef表示RunLoop的运行模式.一个RunLoop可以包含若干个Mode,一个Mode 包含不同的若干个source,timer,observer。
每次RunLoop启动只能指定其中一种模式,可以通过curreMode方法获取
切换mode只能退出Loop,重新再指定一个Mode进入,这样可以分开不同模式下的source,timer,observer
CFRunLoopModeRef以供有5个,其中有两个用不到一个是UIInitializationRunLoopMode 是刚刚进入程序的时候进入的第一个,启动完成后就退出了,还有一个GSEventReceiveRunLoopMode,是系统内部的,也用不到,而且代码根本打不出来,所以可以忽略.
kCFRunLoopCommonModes; //kCFRunLoopDefaultMode|UITrackingRunLoopMode kCFRunLoopDefaultMode;//默认模式,app启动后的模式,主线程就是这个模式 UITrackingRunLoopMode;//界面跟踪模式,追踪触屏滑动,保证界面滑动时候不受其他mode影响
CFRunLoopSourceRef
CFRunLoopSourceRef表示的是事件的输入源。分类1:
- Port-Based Source 基于端口的,内核或者其他线程发过来的信息
- Custom Input Source 自定义的,一般不用
- Cocoa perform selector sources 通过selector消息选择器发送的事件
分类2:
- source0 :非基于port的
- source1 :基于内核的和其他线程通信,接受分发系统事件.
CFRunLoopTimerRef
就是NSTimer,定时器.CFRunLoopObserverRef
可以监听状态runLoop状态变化的观察者.监听runLoop包含下面的状态typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { kCFRunLoopEntry = (1UL << 0),//进入runLoop kCFRunLoopBeforeTimers = (1UL << 1),//即将处理timer事件 kCFRunLoopBeforeSources = (1UL << 2),//即将处理source kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠 kCFRunLoopAfterWaiting = (1UL << 6),//刚从休眠中唤醒 kCFRunLoopExit = (1UL << 7),//runLoop退出了 kCFRunLoopAllActivities = 0x0FFFFFFFU//所有的状态 };
runLoop处理逻辑
官方版本网络版本
runLoop应用
定时器
NSTimer定时器的创建方式第一种:
// 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; // 修改模式 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
第二种:创建一个纯净的定时器,需要自己手动设置运行模式
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; // 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作 // [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; // 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作 // [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; // 定时器会跑在标记为common modes的模式下 // 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
在runLoop状态变化时候做事情
// 创建observer //第一个参数表示如何给observe分配空间,CFAllocatorGetDefault,表示用默认的空间分配器 //第二个参数表示监听的是什么状态,可以检测一种也可以检测所有的 //YES 表示不是监听一次,而是每次通过这个runLoop的时候都监听 //0 位置的参数表示设定优先级,用于多个观察者同时监听一个runLoop的时候,数字越小,优先级越高,默认写0就可以了 //后面的块,可以打印相关的状态 CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"----监听到RunLoop状态发生改变---%zd", activity); }); // 添加观察者:监听RunLoop的状态 //第一个参数.获取添加观察者的runLoop //第二个参数.添加观察者对象 //第三个参数.要监听的模式 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode); // 释放Observer CFRelease(observer);
imageView显示
// 只在NSDefaultRunLoopMode模式下显示图片 [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
可以解决tableView或者scrollView滑动时候卡顿问题,让图片仅仅在不滑动的时候加载.提升用户体验.
创建不死线程
默认状态下线程执行完操作就死亡了,要创建一个不死线程要用runLoop。实现策略:
创建一个线程:
self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(run) object:nil]; [self.thread start];
在线程的run方法里面,添加代码启动新创建的线程的runLoop,
runLoop的run方法,运行的时候如果发现运行模式为空会直接退出,
runLoop不可以没有source,timer,observer.如果3个都没有,就会退出.
所以必须要添加一个保证不退出。
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run];
调用run方法相当下面的情况的一种,都是一致运行到一个非常大的日期,保证不会退出.创造一个死循环.
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
runLoop循环,不会像do while循环卡死,而是一致在不断的运行着,只有当事件触发的时候才会响应时间,没有事件就会休眠.
相关文章推荐
- linux Qt无法自动加载数据库驱动
- Windows,Linux,Mac系统中,USB HID枚举过程的异同
- Windows平台分布式架构实践 - 负载均衡
- 在Windows中构建基于Docker的一致性开发环境
- 架构师漫谈
- Shell基础(二):Bash变量
- OpenGL、DirectX、3DMax之间的相似之处
- Linux设备驱动之mmap设备操作
- centos彻底删除mysql
- tomcat io performance comparison with nio
- Linux查看系统配置常用命令
- DB2 性能监控
- linux驱动开发流程
- GIS+=地理信息+容器技术(2)——Dockers技术介绍
- Nginx,Apache和Tomcat之间的区别
- UltraEdit 和Notepad++ 使用ftp直接编辑linux上文件
- 【opencv图片保存出错问题】
- Tomcat:Can't load AMD 64-bit .dll on a IA 32 platform(问题记录)
- hadoop 数据类型
- shell编程(三):监控信息、进程管理