RunLoop 细节总结

tech2024-08-07  50

1、主线程RunLoop,一般情况运行在 NSDefaultRunLoopMode 模式下,在滑动Scrollview 时候运行在 UITrackingRunLoopMode 模式下。 [runLoop addTimer:timer forMode:NSRunLoopCommonModes] ,NSTimer 添加到 NSRunLoopCommonModes ,才能在上面的两种情况下都执行定时方法。

2、RunLoop有三种启动方式

- (void)run; 

- (void)runUntilDate:(NSDate *)limitDate;

- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;

第一种无条件永久运行 RunLoop 并且无法停止,线程永远存在。NSDefaultRunLoopMode 模式下运行。第二种会在到到达 limitDate 后退出 RunLoop,同样无法主动停止RunLoop。NSDefaultRunLoopMode 模式下运行。第三种可以选定运行模式,并且在到达 limitDate 后  或者  触发了非Timer的事件后,退出 RunLoop 。

第一、二种说明:

因为默认运行在 NSDefaultRunLoopMode 模式下,所以 [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode] ,事件要添加在 NSDefaultRunLoopMode 下。即 Runloop 当前运行 mode 下必现要有 NSTimer 或者 Source 才能运行起来,要不然直接退出。

 

第三种举例:

_kThread 开始一直执行 timer 定时事件,当执行一次 performSelector: onThread:withObject:waitUntilDone: (即source 事件)后,退出 Runloop。

- (void)viewDidLoad { [super viewDidLoad]; [self runModeTest]; } - (void)runModeTest { _kThread = [[NSThread alloc] initWithTarget:self selector:@selector(treadRunLoop) object:nil]; [_kThread start]; } - (void)treadRunLoop { NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timeTest) userInfo:nil repeats:YES]; [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } - (void)timeTest { NSLog(@"=== timeTest"); } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self performSelector:@selector(kkk) onThread:_kThread withObject:nil waitUntilDone:NO]; } - (void)kkk { NSLog(@"=== kkk"); } //=== 打印 === timeTest === timeTest === timeTest === kkk

 

【注】第三种情况测试发现:

当使用

NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timeTest) userInfo:nil repeats:YES]; [runLoop addTimer:timer forMode:NSRunLoopCommonModes]; [runLoop runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]];

定时器不执行,performSelector: 不执行。

当使用

NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timeTest) userInfo:nil repeats:YES]; [runLoop addTimer:timer forMode:UITrackingRunLoopMode]; [runLoop runMode:UITrackingRunLoopMode beforeDate:[NSDate distantFuture]];

定时器执行,performSelector: 不执行。

最新回复(0)