美文网首页
runloop笔记

runloop笔记

作者: TAsama | 来源:发表于2018-12-15 10:39 被阅读0次

runloop运行循环

目的:
  1. 保证程序不退出
  2. 负责监听所有事件
    硬件-->操作系统-->应用程序-->runloop(事件传递流程)
    runloop每做完一件事就进入睡眠
  3. RunLoop在一次循环中渲染UI

runloop的运行模式

  1. DefaultRunLoopMode (只要有事件,就处理)
  2. UITrackingRunloopMode (只有当有UI事件交互发生时,runloop才会切换到,并且该模式会优先切换)
  3. NSRunLoopCommonModes (这并非一种模式,仅仅只是一种占位符,表示同时处在Default和UITracking两种模式下)
runloop处理三件事:
  1. Source:源,输入源
  2. Observer:观察者,观察runloop
  3. Timer:定时器

RunLoop与多线程的关系

当定时器在子线程中运行时,子线程在任务运行结束后会被回收,因此定时器也无法执行。
为什么子线程会被回收呢?因为子线程中的runloop默认是不会开启循环的。
为了让子线程不会被回收,我们要开启子线程的runloop

[[NSRunLoop currentRunLoop] run]; //这是一个死循环

因此我们可以在子线程中进行耗时操作,同时开启子线程中的runLoop,使子线程保持,同时又不会影响主线程。
但是,使用上面的方式开启了runloop后也会产生问题,runLoop不会结束了。我们并不想要这种结果。于是产生了下面的方式

while(_finished) {
    [NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceReferenceDate:0.01f]];
}

这样一来我们可以通过控制finished这个参数来控制runLoop的保持

GCD与RunLoop的关系

看如下代码实例:

@interface ViewController ()
// 声明一个dispatch_source_t对象
@property (nonatomic, strong) dispatch_source_t timer;

@end
- (void)viewDidLoad {
    [super viewDidLoad];
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    dispatch_time_t start_time = DISPATCH_TIME_NOW;
    dispatch_time_t interval = 1.0 * NSEC_PER_SEC;
    // 定时器对象,启动时间,持续时间(纳秒),等待时间
    dispatch_source_set_timer(self.timer, start_time, interval, 0);
    
    //事件
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"----------------------%@", [NSThread currentThread]);
    });
    dispatch_resume(self.timer);
}

定时器全局队列中执行,即子线程中运行,此时,子线程中的runloop就已经被启动了。

处理UI线程的耗时操作

当我们在主线程加载大量图片的时候,主线程会发生卡顿。
原因在与,系统会在一次runloop中渲染UI,除了一次性加载大量内存造成的卡顿外,一次性渲染UI也会造成一定程度的卡顿现象。下面的例子里,我们可以利用RunLoop的监听回调,在runLoop中自定义执行任务。

static void callback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
    
    NSLog(@"%@", info);
}

- (void)addObserver {
    
    CFRunLoopRef runLoop = CFRunLoopGetMain();
    CFRunLoopObserverRef defaultObserver;
    
    CFRunLoopObserverContext context = {
        
        0,
        (__bridge void *)(self),
        &CFRetain,
        &CFRelease,
        NULL
    };
    defaultObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopAfterWaiting, YES, 0, &callback, &context);
    CFRunLoopAddObserver(runLoop, defaultObserver, kCFRunLoopCommonModes);
    CFRelease(defaultObserver);
}

kCFRunLoopAfterWaiting是观察模式,规定当RunLoop被唤醒后,执行回调。所以我们可以用各种方式(比如定时器)来唤醒runloop,每唤醒一次runloop,就执行一次回调,保证每次回调在一个独立的runloop内执行,以此来分散耗时操作。

相关文章

  • RunLoop笔记

    runloop的理解:1.runloop表面意思就是:运行循环2.基本作用:1。保证程序的持续运行(如果没有run...

  • RunLoop笔记

    1:runloop是什么 runloop其实是一个对象,提供一个入口函数,程序启动的时候,程序就会进入一个运行循环...

  • RunLoop笔记

    学习sunny视频笔记 Why Run Loops? 使程序一直运行并接受用户输入 决定程序在何时应该处理哪些事件...

  • RunLoop笔记

    RunLoop是iOS和OSX中基本的概念,掌握RunLoop,能了解到苹果是如何利用RunLoop实现自动释放池...

  • RunLoop 笔记

    RunLoop 是 iOS 开发中非常重要的一个概念,本文是对孙源大神的视频的总结笔记与实践 命令式执行与事件驱动...

  • runloop笔记

    一、RunLoop概念 1、没有消息处理时,休眠已避免资源占用,由用户态切换到内核态 2、有消息需要处理时,立刻被...

  • runloop笔记

    runloop运行循环 目的: 保证程序不退出 负责监听所有事件硬件-->操作系统-->应用程序-->runloo...

  • 喜欢的链接

    ibireme深入理解RunLoop OneV's Den WWDC 2014 Session笔记 - iOS界面...

  • runloop详解

    关于RunLoop的解释和文章有很多,我感觉系统全面解释很好的文章并不多,本来打算整理一下关于RunLoop的笔记...

  • 2020-11-10

    runloop笔记参考:https://www.jianshu.com/p/d260d18dd551

网友评论

      本文标题:runloop笔记

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