ios runloop

作者: BlackStar暗星 | 来源:发表于2019-04-17 18:07 被阅读0次

    runloop相关知识
    runloop 即 运行循环,个人理解为无限循环,优点是能够在闲暇时间等待,有事件则进行分发处理,对资源的占用起到了节源的作用。内部使用do while 实现。

    RunLoop 相关五个类:
    CFRunLoopRef:RunLoop对象
    CFRunLoopModeRef:循环模式
    CFRunLoopSourceRef:输入源/事件源 分为source0和source1
    CFRunLoopTimerRef:定时源
    CFRunLoopObserverRef:观察者

    runloop可以处理几种事件源:
    1、source0:触摸事件等(非基于 Port。只包含了一个回调,不能主动触发事件。使用时,需先调用 CFRunLoopSourceSignal(source),将 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop)唤醒 RunLoop,让其处理这个事件)

    2、source1:系统内部事件(基于Port,通过内核和
    其他线程通信,接收、分发系统事件。 包含了一个 mach_port 和一个回调(函数指针),被用于通过内核和其他线程相互发送消息。这种 Source 能主动唤醒 RunLoop 的线程)

    3、Timer:计时器

    4、Observe:监听runloop的状态
    CFRunLoopObserverRef是观察者,主要用来监听RunLoop 的状态,主要有以下几种状态。
    kCFRunLoopEntry : 即将进入RunLoop
    kCFRunLoopBeforeTimers :即将处理Timer
    kCFRunLoopBeforeSources:即将处理Source
    kCFRunLoopBeforeWaiting :即将进入休眠
    kCFRunLoopAfterWaiting:即将从休眠中唤醒
    kCFRunLoopExit :即将从RunLoop中退出
    kCFRunLoopAllActivities:监听全部状态改变

    runloop 几种 Mode
    1、kCFRunLoopDefaultMode : 默认模式,主线程是在这个运行模式下运行

    2、UITrackingRunLoopMode : 跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)

    3、UIInitializationRunLoopMode : 在刚启动App时第进入的第一个 Mode,启动完成后就不再使用

    4、GSEventReceiveRunLoopMode : 接受系统内部事件,通常用不到

    5、kCFRunLoopCommonModes : 伪模式,不是一种真正的运行模式,实际是kCFRunLoopDefaultMode 和 UITrackingRunLoopMode的结合。

    对于函数运行在哪个输入源 ,我们可以使用断点然后使用 bt(使用方法同 po相同) 进行 堆栈信息输出

    runloop 与线程
    我们都知道程序启动入口是main,那么main返回了一个函数,

    UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    

    这个函数其实起到了一个启动 mainRunloop的作用,程序启动在主线程,我们需要主线程一直保持存在状态,所以需要runloop来支撑,这个runloop就是mainRunLoop,如果没有mainRunLoop程序会立马退出。
    每一个线程最多只能有一个runloop,如果我们需要在子线程运行runloop,需要我们手动启动runloop,[NSRunLoop currentRunLoop] 就可以获取当前runloop,如果runloop存在,则直接拿到,不存在,系统会创建runloop,可以理解为懒加载方式。[[NSRunLoop currentRunLoop] run]; 即启动了runloop。

    实际开发中,我们可能用到的地方:
    1、线程常驻(案例:AFNetworking )
    2、滚动视图和 timer 的使用,滚动视图在滚动状态下,timer停止,将timer加入到commonMode即可。
    3、AutoreleasePool
    应用程序一旦启动,主线程 RunLoop 里注册了两个 Observer。一个 Observer 监听即将进入 Loop 事件,回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池,并保证创建释放池发生在其他所有回调之前。另外一个 Observer 监视了两个事件 (RunLoop即将进入休眠和即将退出 RunLoop 事件) ,前者会调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;后者会调用 _objc_autoreleasePoolPop() 来释放自动释放池,并保证释放自动释放池事件发生在其它回调之后。
    4、卡顿监测
    所谓的卡顿一般是在主线程做了耗时操作,卡顿监测的主要原理是在主线程的 RunLoop 中添加一个 observer,检测从 即将处理Source(kCFRunLoopBeforeSources) 到 即将进入休眠 (kCFRunLoopBeforeWaiting) 花费的时间是否过长。如果花费的时间大于某一个阙值,则认为卡顿,此时可以输出对应的堆栈调用信息。
    参考文章

    相关文章

      网友评论

        本文标题:ios runloop

        本文链接:https://www.haomeiwen.com/subject/chfowqtx.html