一、关于RunLoop
程序启动后会加载一个固定的RunLoop,用以使程序可以一直存活。如果没有RunLoop,程序一启动就被退出了。
RunLoop除了使程序存活,还有的作用就是在程序不在工作的时候,要通知CPU空出来做其他的事情,并等待用户再次进入应用的时候能马上进入工作。
Runloop有五种状态:
1.kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行2.UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
3.UIInitializationRunLoopMode:在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用,会切换到kCFRunLoopDefaultMode
4.GSEventReceiveRunLoopMode:接受系统事件的内部 Mode,通常用不到5.kCFRunLoopCommonModes:这是一个伪Mode,作为标记kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一种真正的Mode
处理定时器的问题
RunLoop最常用的地方是处理NSTimer在ScrollView滚动的时候回停止运行,滚动结束会继续运行。
NSTimer默认添加在默认(kCFRunLoopDefaultMode)状态,在ScrollView滚动的时候RunLoop会被切换到追踪(UITrackingRunLoopMode)状态,所以造成NSTimer的暂停。
解决方法:
1.两种状态都加上NSTimer,但这不是最优解,这样会有2个timer,不是同一个。
2.NSTimer添加的时候选择通用(kCFRunLoopCommonModes),可以理解为,添加为kCFRunLoopCommonModes后,不管是切换到哪一个都是会被执行的,也就不会存在被暂停的问题了。
关于自动释放池(NSAutoreleasePool)的问题
苹果在解释RunLoop的时候,举例了自动释放池。
APP启动后,在RunLoop注册了2个observer,回调在_wrapRunLoopWithAutoreleasePoolHandler()。第一个就是在Entry(即将进入)创建了自动释放池,优先级最高,保证创建释放池发生在其他所有回调之前。另一个是BeforeWaiting(准备进入休眠),在程序退出是释放自动释放池,优先级最低,保证其释放池子发生在其他所有回调之后。
关于方法调用的问题
NSobject调用performSelecter:afterDelay:方法或者performSelector:onThread: ,其实也会调用创建timer的方法。如果当前线程没有 RunLoop,则这个方法会失效。
关于UIImageView的延迟加载
滚动tableView的时候,UIImageView加载会有卡顿,此时,将设置图片的方法推迟到default里面performSelector:withObject:afterDelay:inModes可以较好地保存流畅性。
网友评论