杨小麦OC之旅--RunLoop&&NSTimer

来源:互联网 发布:java求数组的实际长度 编辑:程序博客网 时间:2024/04/27 17:41

6th,Dec,2015

RunLoop
运行在某个线程中的死循环,从事件队列中取出一个事件分派给监听器。多任务最基本的形式是运行循环。
“应用程序由一个处于阻塞状态的do/while循环驱动,当有事件发生时,分派给合适的监听器,如此反复直到循环停止。处理分派的对象就叫做NSRunLoop.”
App运行后能接收到用户事件并执行相应操作,操作完成后然后等待用户事件,直到app退出。线程在执行中的休眠和激活就是由RunLoop对象进行管理的。主线程的运行循环是默认开启的

Cocoa NSRunLoop // 线程不安全
Core Foundation CFRunLoopRef // 线程安全

NSRunLoop
使用:
1.定时器未开启,需手动开启。
比如:NSTimer不用scheduled方式初始化的定时器,需要手动addTimer将timer添加到一个runloop中。

2.某些延迟函数和选择器在分线程中的使用,我们必须手动开启RunLoop


// 获取当前循环
// 获取主线程循环

// 将定时器添加到RunLoop当中。

// 获取下个响应时间

- (NSDate *)limitDateForMode:(NSString *)mode;

如果错过了某个时间点,定时器并不会延时调用,而是直接等待下一个时间点调用,所以定时器并不是精准





定时器
NSTimer基于运行循环进行消息分派
定时器的执行: 不是按照时间间隔进行调用,而是在定时器注册到RunLoop后,设置一个时间点进行调用。错过则不会延迟调用。
// 初始化方法

注:scheduled的初始化方法将以默认mode(NSDefaultRunLoopMode)直接添加到当前的runloop中.
特殊情况:scheduled方法不会执行。
1.当前线程的RunLoop为UI线程时,Mode就切换成其他Mode(NSEventTrackingRunLoopMode),所以默认mode中注册的事件就不会别执行。
2.在scroll一个页面时来松开,此时connection不会收到消息,由于scroll时runloop为UITrackingRunLoopModes模式,不接收输入源,此时要修改connection的mode
不被UI干扰的Timer:使用NSRunLoop的addTimer:forMode:方法来把Timer按照指定模式加入到Run Loop中。这里使用的模式是:NSRunLoopCommonModes,这个模式等效于NSDefaultRunLoopMode和NSEventTrackingRunLoopMode的结合。

RunLoopMode

一个集合,包括监听:事件源,定时器,以及需通知的runloop observers

模式包括:

Default模式:几乎包括所有输入源(除NSConnection) NSDefaultRunLoopMode模式 

Connection模式:处理NSConnection事件,属于系统内部,用户基本不用

Modal模式:处理modal panels

Event tracking模式:如组件拖动输入源 UITrackingRunLoopModes 不处理定时事件 

Common modes模式:NSRunLoopCommonModes 这是一组可配置的通用模式。将input sources与该模式关联则同时也将input sources与该组中的其它模式进行了关联。 





// 声明


// 移除
invalidate是唯一的办法将定时器从RunLoop中注销从循环池中移除的方法。
在某个界面释放前,将这个定时器停止,甚至置为nil,都不能真正释放,原因是系统的循环池中还保有这个对象。




参考资料:
《iOS编程实战》第9章

 iOS中RunLoop机制浅探

RunLoop机制理解

IOS NSTimer 定时器用法总结

iOS:.NSRunLoop再理解








0 0