NSTimer -滑动中的NSTimer

不问归期 提交于 2020-12-01 01:28:27

个人博客地址 NSTimer误差原因 (NSDefaultRunLoopMode 是普通状态下,TrackingRunLoopMode是处于滑动状态)

1,NSTimer添加在主线程中,模式是NSDefaultRunLoopMode, 主线程处理所有添加在主线程中的事件,例如UI界面的刷新,复杂的运算,等等,过多主线程事件的处理,导致线程阻塞。

2,模式的改变,当NSTimer添加到NSDefaultRunLoopMode中的时候,会重复调用,当滑动ScrollView的时候,Runlop会将Model切换到TrackingRunLoopMode,这时候的NSTimer事件就不会回调,所以不准。

<!more->

@interface ViewController ()
/**
 定时器1
 */
@property (nonatomic,strong)NSTimer *timer;
@end

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 主线程
    [self mainThreadTimerOne];
    [self mainThreadTimerTwo];
    
    // 子线程
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(childThreadThree) object:nil];
    [thread start];
    
}

主线程中NSTimer

#pragma mark - 主线程创建定时器
/*
 @NSTimeInterval 设置时间间隔
 @target 发送的对象
 @selector 调用一个实例方法
 @userInfo 用于向selector方法中传参数,
 @repeats 是否重复
 */
- (void)mainThreadTimerOne
{
    _timer = [NSTimer timerWithTimeInterval:9 target:self selector:@selector(changerViewColor:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
}
- (void)mainThreadTimerTwo
{
    _timer = [NSTimer scheduledTimerWithTimeInterval:9 target:self selector:@selector(changerViewColor:) userInfo:nil repeats:YES];
    [_timer fire];// 立即执行
}

子线程中的定时器

注意: 1, 子线程RunLoop默认关闭,需手动开启 2, 子线程定时器结束的时候,需要干掉,否则会造成资源的浪费

#pragma mark - 子线程创建定时器
- (void)childThreadThree
{
    _timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(changerViewColor:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
        
// 终止NSTimer
[self performSelector:@selector(timeInterval) withObject:nil afterDelay:5];
}

#pragma mark - 响应事件
- (void)changerViewColor:(NSTimer *)sender
{
    self.view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1.0];
}
#pragma mark - 定时器释放
- (void)timerInvalidate
{
    [_timer invalidate];
    _timer = nil;
}

解决方案

将NSTimer实例加到main runloop的特定NSRunLoopCommonModes(模式)中。避免被复杂运算操作或者UI界面刷新所干扰。

[[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSRunLoopCommonModes];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!