1:runloop是什么?
runloop是一个循环,它是程序运行的基石;主要功能有:
能够保持程序的持续运行
处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
提高程序性能:有事件需要处理就运行起来;没有任务的时候处于睡眠状态;节省CPU资源;
UIApplication 中一直开启一个runloop来保证程序正常运行.
2:runloop与线程之间的关系
每条线程都有唯一的一个与之对应的RunLoop对象(主线程runloop默认开启,子线程runloop需要手动开启)RunLoop在第一次获取时创建,在线程结束时销毁
3.runloop相关类介绍:
CFRunLoopModeRef:
一个RunLoop包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode(当且仅当指定一个mode)
如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入
这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响
ModeType:
kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响
UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode(是几种mode的集合)
CFRunLoopSourceRef
CFRunLoopSourceRef是事件源(输入源)可以分为两类:
Port-Based Sources (基于端口,跟其他线程交互,通过内核发布的消息)
Custom Input Sources (自定义类型)
Cocoa Perform Selector Sources (performSelector…方法)
包含两种事件:Source0(大多是自定义方法), Source1(基于系统)
Source0: event事件,只含有回调,需要先调用CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop。
Source1: 包含了一个 mach_port 和一个回调,被用于通过内核和其他线程相互发送消息,能主动唤醒 RunLoop 的线程
CFRunLoopObserverRef:
observer:顾名思义就是一个观察者;来观察runloop不同的状态
/* Run Loop Observer Activities */
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), //退出
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
3.runloop处理事件的步骤:
e004412fc56ab75a4e5d53275a4bd41c.jpg
4.runloop实际应用
1.滑动scrollView轮播图轮播失效,是由于定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作.而滑动的时候是trakingMode;解决方法:timer 添加到runloop的commonMode
2.当滑动scrollView时候改变imageView图片
(1)可以监听scrollView滑动事情来做
(2) [imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"trakingModeImageName"] afterDelay:3.0 inModes:@[UITrackingRunLoopMode]];
3.常驻线程
(1)粗暴的方法 while(YES){}
(2)添加source
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
启动RunLoop:[[NSRunLoop currentRunLoop] run]; 退出:[NSThread exit];
参考内容:
http://ios.jobbole.com/85635/…
https://developer.apple.com/l…
http://opensource.apple.com/s…