iOS - scrollView与NSTimer的失效问题详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS - scrollView与NSTimer的失效问题详解相关的知识,希望对你有一定的参考价值。

原创

 

 定时器里面有个runloop mode,一般定时器是运行在defaultmode上。但是如果滑动了这个页面,主线程runloop会转到UITrackingRunLoopMode中,这时候就不能处理定时器了,造成定时器失效,原因就是runroop mode的问题

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
  • UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode
  • UIInitializationRunLoopMode:run loop启动时,会切换到该Mode
  • NSRunLoopCommonModes(kCFRunLoopCommonModes)

 

这里提供了两种解决办法: 
    1. 把定时器添加到当前线程消息循环中 并指定消息循环的模式为
NSRunLoopCommonModes(无论runloop运行在哪个mode,都能运行)
    2. 切换到主线程上更新UI
    // 步骤1. 把NSTimer放到子线程中,但是要注意:因为自线程的消息循环默认不开启,所以这里还需要开启一下子线程的消息循环
    // 步骤2. 切换到主线程上更新UI
 
#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong)UIScrollView *scrollView;
@property(nonatomic,strong)NSTimer *timer;

@property(nonatomic,strong)UILabel *label;
@property(nonatomic,assign)float times;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.scrollView = [[UIScrollView alloc]init];
    self.scrollView.frame = self.view.frame;
    self.scrollView.backgroundColor = [UIColor cyanColor];
    self.scrollView.contentSize = CGSizeMake(375, 2000);
    [self.view addSubview:self.scrollView];
   
    self.label = [[UILabel alloc]init];
    self.label.frame = CGRectMake(100, 100, 100, 100);
    self.label.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.label];
   
    _times = 0;

    //self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(demo) userInfo:nil repeats:YES];
   
    //  解决方法1: 把定时器添加到当前线程消息循环中 并指定消息循环的模式为
    //  cNSRunLoopCommonModes(无论runloop运行在哪个mode,都能运行)
    //  加上这句完美解决
    //[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
   
    //  解决方法2:
    // 1. 把NSTimer放到子线程中,但是要注意:因为自线程的消息循环默认不开启,所以这里还需要开启一下子线程的消息循环
    // 2. 切换到主线程上更新UI
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(demo) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];
       
    });
}

-(void)demo{
   
    _times+=0.1;
   
    //self.label.text = [NSString stringWithFormat:@"%f",_times];

   
    //  队列方式(在主线程上更新UI)
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        self.label.text = [NSString stringWithFormat:@"%f",_times];
    }];
   
    //  GCD方式
    /*dispatch_async(dispatch_get_main_queue(), ^{
       
        self.label.text = [NSString stringWithFormat:@"%f",_times];
    });*/
}

@end






































































以上是关于iOS - scrollView与NSTimer的失效问题详解的主要内容,如果未能解决你的问题,请参考以下文章

NStimer 被堵塞

iOS中NSRunloop与滚动视图时停止加载的问题

iOS中定时器NSTimer的使用/开启与关闭

IOS中定时器NSTimer的开启与关闭

转 IOS中定时器NSTimer的开启与关闭

ios子线程怎样能开启NSTimer