iOS基础知识4
来源:互联网 发布:淘宝申请延长收货时间 编辑:程序博客网 时间:2024/06/05 06:12
一、RunLoop和线程有什么关系?
每个线程,包括主线程(main thread),都有与之对应的RunLoop对象。
主线程的RunLoop是默认启动的,子线程的RunLoop默认是不开启的,需要手动开启子线程的RunLoop。
iOS程序里面,程序启动后会有这样的一个main()函数:
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); }}这是主循环,保证我们的程序一直运行下去。
UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
对其它线程来说,RunLoop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
在任何一个Cocoa程序的线程中,都可以通过以下代码来获取到当前线程的RunLoop。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];RunLoop在执行完毕后,就会进入休眠,只有在某个情况触发了,RunLoop才会继续被调用。
二、RunLoop的mode作用是什么?
Mode主要是用来指定事件在运行循环中得优先级,有:
1、NSDefaultRunLoopMode(KCFRunLoopDefaultMode) -> 默认
2、UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode
3、UIInitializationRunLoopMode -> Run Loop启动时,会切换到该Mode
4、NSRunLoopCommonModes(KCFRunLoopCommonModes) -> Mode集合
苹果公开的Mode有两个:
NSDefaultRunLoopMode(KCFRunLoopDefaultMode)和NSRunLoopCommonModes(KCFRunLoopCommonModes)
在编程中如果我们把一个NSTimer对象以NSDefaultRunLoopMode(KCFRunLoopDefaultMode)添加到主运行循环中,ScrollView滚动过程中会因为Mode的切换,而导致NSTimer将不再被调度。当我们滚动的时候,也希望不调度,那就应该使用默认模式。但是,如果我们希望ScrollView在滚动时,计时器也要回调,那就应该使用NSRunLoopCommonModes(KCFRunLoopCommonModes)。
三、以+scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?
RunLoop只能运行在一种mode下,如果要换mode,当前的loop也需要停下来重启成新的mode。ScrollView滚动过程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动。
如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候,ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。
所以:
Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)来解决。
四、猜想RunLoop内部是如何实现的?
本质:内部就是 do-while 循环,在这个循环内部不断地处理各种事件(任务),比如:Source、Timer、Observer。
每条线程都有唯一一个RunLoop对象与之对应,主线程的RunLoop默认已经启动 。
子线程的RunLoop需要手动启动。
每次RunLoop启动时,只能指定其中一个mode,这个mode被称作currentMode。
如果需要切换mode,只能退出loop,再重新指定一个mode进入,这样做主要是为了隔离不同mode中的Source、Timer、Observer,让其互不影响。
一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的:
function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit);}伪代码while循环:
// http://weibo.com/luohanchenyilong/// https://github.com/ChenYilongint main(int argc, char * argv[]) { //程序一直运行状态 while (AppIsRunning) { //睡眠状态,等待唤醒事件 id whoWakesMe = SleepForWakingUp(); //得到唤醒事件 id event = GetEvent(whoWakesMe); //开始处理事件 HandleEvent(event); } return 0;}
- iOS基础知识4
- iOS 基础知识
- iOS基础知识
- IOS基础知识
- ios基础知识
- ios基础知识
- IOS基础知识
- ios基础知识
- IOS基础知识
- iOS 基础知识
- IOS-基础知识
- ios基础知识
- iOS基础知识
- iOS基础知识
- UITextField - iOS - UI基础知识总结4
- IOS开发基础知识要点
- ios开发一些基础知识
- ios 内存管理基础知识
- 第二十五节:父子、兄弟、相邻节点定位方式详解
- 使用Dom4j解析XML
- 电话号码问题
- java面向对象(三)之抽象类,接口
- file error / encoding
- iOS基础知识4
- C# 多线程(lock,Monitor,Mutex,同步事件和等待句柄)
- 自适应和响应式的区别
- GPL协议
- 从零开始学Scala系列(五)之集合2--Set和Map
- 重叠相加法&重叠保留法
- CSS基本语法 和 样式规则
- AsyncTask学习笔记
- more effective C++条款五解析