美文网首页
iOS - NSRunLoop

iOS - NSRunLoop

作者: iOS资深入门 | 来源:发表于2019-04-04 15:08 被阅读0次

NSRunLoop - 运行循环 - 是一个死循环

UIApplicationMain返回值为int类型,UIApplicationMain内部开启一个主线程,保证Runloop所在线程不退出。

目的:
-- 保证程序不退出。 本质,保证Runloop所在线程不退出。
-- 负责监听事件。 (触摸,时钟,网络)

每条线程都有一个RunLoop,但是默认都不开启(run)。子线程需要手动开启,主线程由系统 自动开启。
//@property (nonatomic, strong) NSThread * thread; 只保存了对象,没有保持线程。

    //Runloop 5种模式
    /**
     
     NSRunLoopCommonModes           - 占位模式(UI && 默认)
     NSDefaultRunLoopMode           - 默认模式 处理非NSConnection对象的事件。
     UITrackingRunLoopMode          - UI模式  只有发生UI事件时才会生效。    专门处理UI事件。
     GSEventReceiveRunLoopMode      - 用于接受系统事件,属于内部的Run Loop模式。
     UIInitializationRunLoopMode    - 在刚启动App时进入的第一个Mode,启动完成后不再使用

//以下是官方文档中的五种模式,跟其他资料看到的不太一样,有清楚的请指教。
     NSRunLoopCommonModes
     Objects added to a run loop using this value as the mode are monitored by all run loop modes that have been declared as a member of the set of “common" modes; see the description of CFRunLoopAddCommonMode for details.
     NSDefaultRunLoopMode
     The mode to deal with input sources other than NSConnection objects.
     NSEventTrackingRunLoopMode
     A run loop should be set to this mode when tracking events modally, such as a mouse-dragging loop.
     NSModalPanelRunLoopMode
     A run loop should be set to this mode when waiting for input from a modal panel, such as NSSavePanel or NSOpenPanel.
     UITrackingRunLoopMode
     The mode set while tracking in controls takes place. You can use this mode to add timers that fire during tracking.
     */
    

Source0:只包含了一个回调(函数指针),并不能主动发出事件,需要先调用CFRunLoopSourceSignal(source)将这个source标记为待处理,然后主动调用CFRunLoopWeakUp(runloop)来唤醒runloop
非系统内核事件的处理。
Source1:包含了一个mach-port和一个回调(函数指针),被用于通过内核和其他线程相互发送消息,这种Source能主动唤醒runloop

    //创建定时器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    //设置定时器的属性
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    //设置回调
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"------%@",[NSThread currentThread]);
    });
    //启动
    dispatch_resume(timer);

Timer

    NSThread * thread = [[NSThread alloc] initWithBlock:^{
        NSTimer * timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        [[NSRunLoop currentRunLoop] run];//开启循环,循环执行完成之前,下面代码不执行。
        NSLog(@"%@",[NSThread currentThread]);
    }];
    [thread start];

Observer

typedef void(^RunloopBlock)(void);

//任务数组 存放任务。
@property (nonatomic, strong) NSMutableArray<RunloopBlock> * taskes;

//添加Runloop的观察者
- (void)addRunloopObserver{
    //获取runloop
    CFRunLoopRef runloop = CFRunLoopGetCurrent();
    //定义观察者
    static CFRunLoopObserverRef defaultModeObserver;
    //创建上下文
    CFRunLoopObserverContext context = {
        0,
        (__bridge void *)(self),//传入self,方便之后操作。如果不需要,&context直接传nil。
        &CFRetain,
        &CFRelease,
        NULL,
    };
    //创建观察者 ,
    defaultModeObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES, 0, &callBack, &context);
    /**
     kCFRunLoopBeforeWaiting观察NSRunLoop等待之前,如果需要一直观察,可以添加下列代码,不过要注意CPU使用率。。。。并不好用。。。。
     [NSTimer scheduledTimerWithTimeInterval:0.001 repeats:YES block:^(NSTimer * _Nonnull timer) {
        //什么都不做,只为保持RunLoop活动。
     }];
    */
    //添加观察者到当前runLoop中
    CFRunLoopAddObserver(runloop, defaultModeObserver, kCFRunLoopDefaultMode);
}

//回调
static void callBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
    
    NSLog(@"%@",[NSThread currentThread]);
    //取出任务 执行
    ViewController * vc = (__bridge ViewController*)info;
    if (vc.taskes.count == 0) {
        return;
    }
    RunloopBlock task = vc.taskes.firstObject;
    task();
    [vc.taskes removeObjectAtIndex:0];
}
//NSTimer 两个创建方法的区别。

/// Creates and returns a new NSTimer object initialized with the specified block object. This timer needs to be scheduled on a run loop (via -[NSRunLoop addTimer:]) before it will fire.
//创建并返回新初始化的NSTimer对象,需要手动添加到NSRunLoop中,才能启动。
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

/// Creates and returns a new NSTimer object initialized with the specified block object and schedules it on the current run loop in the default mode.
//创建并返回新初始化的NSTimer对象,并自动在当前NSRunLoop的默认模式下进行调用。
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

@autoreleasepool

App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler()。
第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。
第二个 Observer 监视了两个事件: BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。

autoreleasepool引用:
作者:thinkq
链接:https://www.jianshu.com/p/a2999d7728b4
来源:简书

扩展
https://blog.ibireme.com/2015/05/18/runloop/

相关文章

  • NSRunLoop作用

    NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执行和...

  • NSRunLoop

    NSRunLoop--NSRunLoop是IOS消息机制的处理模式,控制NSRunLoop里面线程的执行和休眠,在...

  • NSRunLoop 详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • NSRunLoop详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • 【转】NSRunLoop详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • iOS面试题06-应用程序(★★)

    《2018 iOS面试题系列》 一、NSRunLoop的实现机制,及在多线程中如何使用 NSRunLoop是IOS...

  • runloop

    NSRunLoop:OSX/iOS 系统中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef...

  • 实现定时器功能的几种方式

    nsrunLoopGCDRAC NsrunLoop NSRunLoop是IOS消息机制的处理模式 一条线程对应一个...

  • NSRunLoop的使用

    版本:iOS13.6 本文仅介绍api的作用若想了解NSRunloop,可点击NSRunloop 简单细说。若想了...

  • NSTimer

    深入NSTimer(iOS)iOS 中的 NSTimer关于NSRunLoop和NSTimer的深入理解

网友评论

      本文标题:iOS - NSRunLoop

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