标签:监控 detail processor 常用 mod hand opd func out
一、什么是RunLoop
1.从字面意思看
1)运行循环
2)跑圈
2.基本作用
1)保持程序的持续运行
2)处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
3)节省CPU资源,提高程序性能:该做事时做事,该休息时休息
4)......
3.如果没有RunLoop
说明:没有RunLoop的情况下,程序执行到第3行后程序就结束了
4.如果有了RunLoop
说明:有RunLoop的情况下,由于main函数里面启动了个RunLoop,所以程序并不会马上退出,保持持续运行状态
5.main函数中的RunLoop
1)第14行代码UIApplicationMain函数内部就启动了一个RunLoop,
2)所以UIApplicationMain函数一直没有返回, 保持了程序的持续运行,
3)这个默认启动的RunLopp是跟主线程相关联的
二、RunLoop对象
1.iOS中有2tAPI来访问和使用RunLoop
1)Foundation 框架
NSRunLoop
2)Core Foundation
CFRunLoopRef
2.NSRunLoop和CFRunLoopRef都代表着RunLoop对象
3.NSRunLoop是基于CFRunLoopRef的一层OC包装, 所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API (Core Foundation 层面)
三、RunLoop资料
1.苹果官方文档
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html
2.CFRunLoopRef是开源的
http://opensource.apple.com/source/CF/CF-1151.16/
四、RunLoop与线程
1.每条线程都有唯一的一个与之对应的RunLoop对象
2.主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
3.RunLoop在第一次获取时创建,在线程结束时销毁
4.获取RunLoop对象
1)Foundation
- [NSRunLoop currentRunLoop];
- [NSRunLoop mainRunLoop];
2)Core Foundation
- CFRunLoopGetCurrent();
- CFRunLoopGetMain();
代码示例:
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
-
- NSRunLoop *mainRunLoop = [NSRunLoop mainRunLoop];
- NSLog(@"mainRunLoop = %@", mainRunLoop);
-
-
- NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
- NSLog(@"currentRunLoop = %@", currentRunLoop);
-
-
- CFRunLoopRef cfMainRunLoop = CFRunLoopGetMain();
- NSLog(@"cfMainRunLoop = %@", cfMainRunLoop);
-
- CFRunLoopRef cfCurrentRunLoop = CFRunLoopGetCurrent();
- NSLog(@"cfCurrentRunLoop = %@", cfCurrentRunLoop);
-
-
- NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
-
- [thread start];
- }
-
- - (void)run
- {
-
-
- [NSRunLoop currentRunLoop];
- }
-
- @end
5.RunLoop相关类
CoreFoundation中关于RunLoop的5个类
1)CFRunLoopRef
2)CFRunLoopModeRef
3)CFRunLoopSourceRef
4)CFRunLoopTimerRef
5)CFRunLoopObserverRef
6.CFRunLoopModeRef
6.1 CFRunLoopModeRef代表RunLoop的运行模式
1)一个 RunLoop包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
2)每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode
3)如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入,这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响
6.2系统默认注册了5个Mode:
1)kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
2)UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode 影响
3)UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
4)GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
5)kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
代码示例:
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @property (nonatomic, strong) dispatch_source_t timer;
-
- @end
-
- @implementation ViewController
-
- - (void)viewDidLoad {
- [super viewDidLoad];
- }
-
- - (IBAction)btnClick:(id)sender {
- NSLog(@"%s", __func__);
- }
-
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
-
- [self gcdTimer];
- }
-
- - (void)gcdTimer
- {
- NSLog(@"%s", __func__);
-
-
-
-
- dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
-
- self.timer = timer;
-
-
-
- dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC);
-
- uint64_t interval = 1.0 * NSEC_PER_SEC;
-
- dispatch_source_set_timer(timer, startTime, interval, 00 * NSEC_PER_SEC);
-
-
- dispatch_source_set_event_handler(timer, ^{
- NSLog(@"test-----%@", [NSThread currentThread]);
- });
-
-
- dispatch_resume(timer);
-
- }
-
- - (void)timer1
- {
- NSLog(@"-----start-----");
-
- NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
-
-
-
-
-
- [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- }
-
- - (void)timer2
- {
-
- NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
-
- [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
-
-
-
- [[NSRunLoop currentRunLoop] run];
- }
-
- - (void)show
- {
- NSLog(@"%s-----%@", __func__, [NSThread currentThread]);
- }
- @end
7.CFRunLoopSourceRef
7.1 CFRunLoopSourceRef是事件源(输入源)
7.2 以前的分法
1) Port-BasedSources
2) Custom InputSources
3) Cocoa PerformSelector Sources
7.3 现在的分法
1)Source0:非基于Port的,用于用户主动触发的事件
2)Source1:基于Port的,通过内核和其它线程相互发送消息
8.CFRunLoopTimerRef
1)CFRunLoopTimerRef是基于时间的触发器
2)基本上说的就是NSTimer,它会受到runloop的mode的影响
3)GCD的定时器不受Runloop的mode的影响
9.CFRunLoopObserverRef
CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
可以监听的时间点有以下几个
10. CFRunLoopObserverRef
10.1 添加Observer
- CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
- NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
- });
-
- CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
-
- CFRelease(observer);
代码示例:
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
-
-
- CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
- switch (activity) {
- case kCFRunLoopEntry:
- NSLog(@"即将进入RunLoop");
- break;
- case kCFRunLoopBeforeTimers:
- NSLog(@"即将处理timer");
- break;
- case kCFRunLoopBeforeSources:
- NSLog(@"即将处理source");
- break;
- case kCFRunLoopBeforeWaiting:
- NSLog(@"即将进入睡眠");
- break;
- case kCFRunLoopAfterWaiting:
- NSLog(@"RunLoop刚从睡眠中唤醒");
- break;
- case kCFRunLoopExit:
- NSLog(@"RunLoop即将退出");
- break;
- default:
- break;
- }
- });
-
-
-
- CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
-
-
- CFRelease(observer);
-
- [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
-
- }
-
- - (void)show{
- NSLog(@"%s", __func__);
- }
-
- @end
打印查看:
五、CF的内存管理(CoreFoundation)
1. 凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
比如CFRunLoopObserverCreate
release函数:CFRelease(对象);
六、RunLoop处理逻辑
1.官方版本
2.网友整理版本
七、RunLoop应用
1.NSTimer
2.ImageView显示
3.PerformSelector
4.常驻线程
5.自动释放池
代码示例:
执行效果请自行演示
八、RunLoop面试题
1. 什么是RunLoop?
1)从字面意思看:运行循环、跑圈
2)其实它内部就是do-while循环,在这个循环内部不断地处理各种任务(比如Source、Timer、Observer)
3)一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(调用run方法)
4)RunLoop只能选择一个Mode启动,如果当前Mode中没有任何Source(Sources0、Sources1)、Timer,那么就直接退出RunLoop
2.自动释放池什么时候释放?
通过Observer监听RunLoop的状态
3.在开发中如何使用RunLoop?什么应用场景?
3.1 开启一个常驻线程(让一个子线程不进入消亡状态,等待其他线程发来消息,处理其他事件)
1)在子线程中开启一个定时器
2)在子线程中进行一些长期监控
3.2 可以控制定时器在特定模式下执行
3.3可以让某些事件(行为、任务)在特定模式下执行
3.4可以添加Observer监听RunLoop的状态,比如监听点击事件的处理(在所有点击事件之前做一些事情)
iOS开发多线程-RunLoop
标签:监控 detail processor 常用 mod hand opd func out
原文地址:http://www.cnblogs.com/dannygao/p/7143414.html