美文网首页
iOS RunLoop

iOS RunLoop

作者: iOS_tree | 来源:发表于2024-01-07 14:38 被阅读0次

1.RunLoop使用

RunLoop又称运行循环,保证app程序一直运行的的基础。
一般程序在运行完代码后就结束运行,要时程序一直运行,则需要一个while循环,保证程序不退出。RunLoop就是这样的角色存在,在有任务时处理任务,没有任务时进入休眠状态。
在iOS开发中,RunLoop与线程为一一对应的关系,每个线程有自己的RunLoop,线程与RunLoop的关系保存在一个全局字典中,key为线程,value为RunLoop。主线程RunLoop为系统启动,无需程序员管理,子线程的RunLoop为懒加载,需要程序员主动调用才会创建,否则子线程执行完任务就退出。
苹果官方的RunLoop示意图如下:

RunLoop运行图
官方文档

简单创建一个线程并激活RunLoop代码如下:


@interface ViewController ()

@property(nonatomic,weak)NSThread* thread;

@end



@implementation ViewController

- (void)ThreadRun:(id)object {
    NSLog(@"%@",[NSThread currentThread]);

    NSLog(@"%s %@",__FUNCTION__,object);
}


- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        //添加port才能激活
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        //添加定时器也可以激活
        //NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            //NSLog(@"block run");
        //}];
        //[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];
    }];
    [thread start];
    self.thread = thread;
    
    
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //可以在该线程不断添加新任务
    [self performSelector:@selector(ThreadRun:) onThread:self.thread withObject:self waitUntilDone:NO];
}


@end

RunLoop每次运行需要处理的事件分为3类:Observer监听事件,Timer定时器事件与Source输入源事件。其中,Source输入源事件又可以分为Source0和Source1:Source0事件不会主动触发,需要将其标记为待处理之后手动唤醒RunLoop进行处理;Source1事件会主动唤醒RunLoop进行处理,通常用来线程间通信和处理硬件接口的信号。Timer事件特指定时器的回调,当定时器被添加进RunLoop时,会根据设置的定时器频率在RunLoop中注册一系列的时间点,当时间点到时会唤醒RunLoop进行事件处理。Observer事件用来监听RunLoop状态的变化,当RunLoop状态变化时会触发对应的回调。
有需要的时候我们可以添加监听,方法如下,可以在排查app卡顿的时候使用。

CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
  NSLog(@"%lu",activity);
});
 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

2.RunLoop的模式

RunLoop可以通过模式来筛选其要处理的事件,NSRunLoopMode为字符串类型,用户除了可以使用系统设置的Mode,也可以自定义Mode

typedef NSString * NSRunLoopMode NS_TYPED_EXTENSIBLE_ENUM;

供用户使用的mode如下,当我们需要在滑动页面添加定时器时,可以把定时器添加到NSRunLoopCommonModes。

FOUNDATION_EXPORT NSRunLoopMode const NSDefaultRunLoopMode;
FOUNDATION_EXPORT NSRunLoopMode const NSRunLoopCommonModes API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

系统使用的mode如下,这些mode我们无需使用。

NSRunLoopCommonModes  //A pseudo-mode that includes one or more other run loop modes.
NSDefaultRunLoopMode //The mode set to handle input sources other than connection objects.
NSEventTrackingRunLoopMode  //The mode set when tracking events modally, such as a mouse-dragging loop.
NSModalPanelRunLoopMode  //The mode set when waiting for input from a modal panel, such as a save or open panel.
UITrackingRunLoopMode  //The mode set while tracking in controls takes place.

相关文章

网友评论

      本文标题:iOS RunLoop

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