博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RunLoop与Timer以及常用Mode
阅读量:6116 次
发布时间:2019-06-21

本文共 4986 字,大约阅读时间需要 16 分钟。

创建一个新的项目就不说了,在主控制器上添加一个可以滑动的UI控件,这边我选择UITextView

直接上代码,代码已经注释的很清楚了

@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    _finished = NO;    /*创建一个定时器(以这种方式创建的定时器会被自动添加到当前的RunLoop中并且自动开始计时,很显然当前的RunLoop的Mode是NSDefaultRunLoopMode)*/    //scheduledTimerWithTimeInterval开头设置的定时器都会自动添加到当前RunLoop的NSDefaultRunLoopMode下    NSTimer *timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeMethod1) userInfo:nil repeats:YES];    //在界面上添加一个UITextView,里面设置足够多的文本以让它可以滑动,当我们滑动文本框的时候当前的的RunLoop的Mode会切换到UITrackingRunLoopMode用于处理UI的滚动等时间,这时timer因为是设置在NSDefaultRunLoopMode下才计时,故此时timer会暂停计时,知道处理完UI滚动等事件RunLoop再次切换回NSDefaultRunLoopMode这时timer才会继续计时.    //NSRunLoopCommonModes表示的是NSDefaultRunLoopMode或UITrackingRunLoopMode,也就是说如果把timer设置在NSRunLoopCommonModes下,当RunLoop的Mode为NSDefaultRunLoopMode或UITrackingRunLoopMode计时器都可以正常计时        //创建一个定时器,与上面定时器不同的是该定时器并不会自动添加到当前的RunLoop下,并且不会自动开始计时(可以运行一下,就知道timeMethod2)    NSTimer *timer2 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod2) userInfo:nil repeats:YES];    //如果我们手动开始计时,你回发现@"timeMethod2"只被打印一次就停止了,那时因为timer2并没有被添加到任何的RunLoop中    [timer2 fire];        //在创建一个定时器,与timer2不同的是我们把timer3手动添加到当前NSRunLoop中,此时计时器就会自动开始计时无需手动调用[timer3 fire]    NSTimer *timer3 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod3) userInfo:nil repeats:YES];    [[NSRunLoop currentRunLoop] addTimer:timer3 forMode:NSDefaultRunLoopMode];    [timer3 fire];//此时计时器就会自动开始计时无需手动调用        //上面timer1与timer3都是添加到当前的RunLoop中去,并且是在NSDefaultRunLoopMode下,此时只要滑动界面的UI,这两个定时器timer1与timer3都会暂停计时,为了让计时器在UI滚动时也可以正常计时,我们试着把计时器添加在当前RunLoopMode的UITrackingRunLoopMode模式下    NSTimer *timer4 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod4) userInfo:nil repeats:YES];    [[NSRunLoop currentRunLoop] addTimer:timer4 forMode:UITrackingRunLoopMode];    //此时UI滚动时也timer4正常计时,现在在timeMethod4添加[NSThread sleepForTimeInterval:1.0];来模拟处理耗时操作,运行,在滑动UI你会发现虽然计时可以正常计时,但是明显感到了UI滚动时的卡顿,那时因为你在UITrackingRunLoopMode模式下处理了耗时的操作,此时的RunLoop纪要处理UI滚动也处理耗时操作自然会卡顿,显然不妥        //解决timer4的问题,创建一个定时器,并且把他放到子线程中去,子线程我们这边使用继承自NSThread的自定义线程PJThread    PJThread *pjThread1 = [[PJThread alloc] initWithBlock:^{        NSTimer *timer5 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod5) userInfo:nil repeats:YES];    }];    //线程跑起来    [pjThread1 start];    //pjThread1执行后我们并没有看到"timeMethod5"被打印,并且打印出"PJThread 被销毁了!",说明pjThread1执行完就被销毁了,而timer5没有计时打印出"timeMethod5"是因为他没有被添加到任何RunLoop下        //解决pjThread1与timer5的问题,我们在创建pjThread2与timer6    PJThread *pjThread2 = [[PJThread alloc] initWithBlock:^{        NSTimer *timer6 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod6) userInfo:nil repeats:YES];        //[NSRunLoop currentRunLoop]会获取当前的RunLoop,**如果当前没有则会创建一个**        NSRunLoop *runLoop1 = [NSRunLoop currentRunLoop];        //在NSRunLoopCommonModes下也是可以的,但是苹果官方推荐NSDefaultRunLoopMode,在runLoop1下已经不会受到UI滚动的影响了        [runLoop1 addTimer:timer6 forMode:NSDefaultRunLoopMode];        //run之后代码会一直死循环在此处不会往下执行,所以"runLoop1执行之后!"是不会被打印的        [runLoop1 run];        NSLog(@"runLoop1执行之后!");    }];    [pjThread2 setName:@"pjThread2"];    //线程跑起来    [pjThread2 start];    //此时timer6可以正常计时了,并且pjThread2也没有被销毁了,滑动UI也不会卡顿了,timer6在UI滚动时也可以正常计时,处理耗时操作,这是因为[runLoop1 run]之后代码会一直死循环在此处不会往下执行,所以"runLoop1执行之后!"是不会被打印的,并且pjThread2也不会被销毁        __weak typeof(self) weakSelf = self;    PJThread *pjThread3 = [[PJThread alloc] initWithBlock:^{        NSTimer *timer7 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeMethod7) userInfo:nil repeats:YES];        //[NSRunLoop currentRunLoop]会获取当前的RunLoop,**如果当前没有则会创建一个**        NSRunLoop *runLoop2 = [NSRunLoop currentRunLoop];        //在NSRunLoopCommonModes下也是可以的,但是苹果官方推荐NSDefaultRunLoopMode,在runLoop1下已经不会受到UI滚动的影响了        [runLoop2 addTimer:timer7 forMode:NSDefaultRunLoopMode];        //runUntilDate表示每隔多久执行一次runLoop,我们设置点击屏幕就让finished为真YES,看能不能达到退出循环打印"runLoop2执行之后!"(RunLoop执行速度很快,故设置0.01够了),实际运行时可以打印"runLoop2执行之后!",并且也打印"PJThread : pjThread3 被销毁了!"        while(!weakSelf.finished){            [runLoop2 runUntilDate:[NSDate dateWithTimeIntervalSinceReferenceDate:0.01]];        }        NSLog(@"runLoop2执行之后!");    }];    [pjThread3 setName:@"pjThread3"];    //线程跑起来    [pjThread3 start];        //到此暂时结束,线程和RunLoop的关系是非常密切的,一个线程要保持一致运行部退出需要RunLoop来帮助实现}- (void)timeMethod1{    NSLog(@"timeMethod1");}- (void)timeMethod2{    NSLog(@"timeMethod2");}- (void)timeMethod3{    NSLog(@"timeMethod3");}- (void)timeMethod4{    [NSThread sleepForTimeInterval:1.0];    NSLog(@"timeMethod4");}- (void)timeMethod5{    [NSThread sleepForTimeInterval:1.0];    NSLog(@"timeMethod5");}- (void)timeMethod6{    [NSThread sleepForTimeInterval:1.0];    NSLog(@"timeMethod6");}- (void)timeMethod7{    [NSThread sleepForTimeInterval:1.0];    NSLog(@"timeMethod7");}- (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event{ self.finished = YES;}@end复制代码

转载地址:http://slvka.baihongyu.com/

你可能感兴趣的文章
嵌入式,代码调试----GDB扫盲
查看>>
类斐波那契数列的奇妙性质
查看>>
配置设置[Django]引入模版之后报错Requested setting TEMPLATE_DEBUG, but settings are not configured....
查看>>
下一步工作分配
查看>>
Response. AppendHeader使用大全及文件下载.net函数使用注意点(转载)
查看>>
Wait Functions
查看>>
代码描述10313 - Pay the Price
查看>>
jQuery最佳实践
查看>>
centos64i386下apache 403没有权限访问。
查看>>
vb sendmessage 详解1
查看>>
jquery用法大全
查看>>
Groonga 3.0.8 发布,全文搜索引擎
查看>>
PC-BSD 9.2 发布,基于 FreeBSD 9.2
查看>>
网卡驱动程序之框架(一)
查看>>
css斜线
查看>>
Windows phone 8 学习笔记(3) 通信
查看>>
重新想象 Windows 8 Store Apps (18) - 绘图: Shape, Path, Stroke, Brush
查看>>
Revit API找到风管穿过的墙(当前文档和链接文档)
查看>>
Scroll Depth – 衡量页面滚动的 Google 分析插件
查看>>
Windows 8.1 应用再出发 - 视图状态的更新
查看>>