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

时间: 2024-12-22 08:57:24

iOS - scrollView与NSTimer的失效问题详解的相关文章

Swift使用WKWebView在iOS应用中调用Web的方法详解

这篇文章主要介绍了Swift使用WKWebView在iOS应用中调用Web的方法详解,使用WKWebView便等于使用和Safari中相同的JavaScript解释器,用来替代过去的UIWebView,需要的朋友可以参考下 自从iOS8开始,Apple引入了WKWebView欲代替UIWebView.相比而言,WKWebView消耗内从更少,功能也更加强大.让我们来看看WKWebView怎么使用吧! 0.初始化(1)首先需要引入WebKit库 复制代码代码如下: #import <WebKit/

IOS问题汇总:2015-1-9 IOS之NSArray 中调用的方法详解(转)

IOS之NSArray 中调用的方法详解 下面的例子以 NSArray *array = [NSArray arrayWithObjects:@“wendy”,@“andy”,@“tom”,@“jonery”,@“stany”, nil];1.获取数组中总共有多少个对象. -(NSUInteger)count; NSLog(@“%d”,[array count]); 2 2.获取数组中下标对应的元素对象.(下标是从0开始) -(id)objectAtIndex:(NSUInteger)index

iOS开发——UI篇OC篇&amp;SpriteKit详解

SpriteKit详解 SpriteKit,iOS/Mac游戏制作的新纪元 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的理解合作.如果您觉得本站对您能有帮助,您可以使用RSS或邮件方式订阅本站,这样您将能在第一时间获取本站信息. 本文涉及到的WWDC2013 Session有 Session 502 Introduction to Sprite Kit Session 503 D

iOS开发——实用篇&amp;KVO与KVC详解

KVO与KVC详解 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听(KVO)特性: 键值编码KVC 键值监听KVO 键值编码KVC 我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象.其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Valu

iOS开发——代码生成TabBar与视图切换详解

我在之前多篇博客中讲解了在不使用storyboard而使用nib文件的情况下,使用代码生成导航栏并进行跳转,具体可以参考<iOS开发--界面跳转与返回及视图类型详解><iOS纯代码实现界面建立.跳转.导航栏(无storyboard.无nib)(Objective-C)>.今天我来讲解下在使用nib搭建界面的情况下,用代码生成TabBar,并进行界面之间的跳转.代码示例已经上传至:https://github.com/chenyufeng1991/TabBarTest   . (1)

iOS开发——UI篇OC篇&amp;UICollectionView详解+实例

UICollectionView详解+实例 实现步骤: 一.新建两个类 1.继承自UIScrollView的子类,比如HMWaterflowView * 瀑布流显示控件,用来显示所有的瀑布流数据 2.继承自UIView的子类,比如HMWaterflowViewCell * 代表着瀑布流数据中的一个单元(一个格子) 3.总结 HMWaterflowView和HMWaterflowViewCell的关系实际上类似于 UITableView和UITableViewCell的关系 二.设计HMWater

iOS开发——UI篇OC篇&amp;UIStackView详解

UIStackView详解 一.继承关系.遵守协议.隶属框架及可用平台 UIStackView 类提供了一个高效的接口用于平铺一行或一列的视图组合.Stack视图使你依靠自动布局的能力,创建用户接口使得可以动态的调整设备朝向.屏幕尺寸及任何可用范围内的变化.Stack视图管理着所有在它的 arrangedSubviews 属性中的视图的布局.这些视图根据它们在 arrangedSubviews 数组中的顺序沿着 Stack 视图的轴向排列.精确的布局变量根据 Stack 视图的 axis , d

iOS开发——网络编程Swift篇&amp;Alamofire详解

Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AFNetworking非常稳定,在Mac OSX与iOS中也能像其他Objective-C代码一样用Swift编写.不过Alamofire更适合Swift语言风格习惯(Alamofire与AFNetworking可以共存一个项目中,互不影响). Alamofire 取名来源于Alamo Fire fl

iOS开发中的UDID和UUID详解

今天突然想和大家聊聊UDID和UUID的问题,虽然平时我们对这两个东西很忽视,往往也很难区分这两个东西.今天就来好好谈谈. [UDID] UDID的全名为 Unique Device Identifier :设备唯一标识符.从名称上也可以看出,UDID这个东西是和设备有关的,而且是只和设备有关的,有点类似于MAC地址.我在上一篇博客中<iOS应用发布流程详解>提到了真机调试,然后需要把UDID这个东西添加到Provisoning Profile授权文件中,也就是把设备唯一标识符添加进去,以此来