IOS开发入门iOS 多线程编程(十五、RunLoop简单介绍)
白羽 2019-07-10 来源 :网络 阅读 564 评论 0

摘要:本文将带你了解IOS开发入门iOS 多线程编程(十五、RunLoop简单介绍),希望本文对大家学IOS有所帮助。

    本文将带你了解IOS开发入门iOS 多线程编程(十五、RunLoop简单介绍),希望本文对大家学IOS有所帮助。

IOS开发入门iOS 多线程编程(十五、RunLoop简单介绍)

一:什么是RunLoop
   (1)从字面意思看,运行循环、跑圈。
   (2)保持程序持续运行,处理App中的各类事件包括触摸事件、定时器事件、Selector事件。
   (3)节省CPU资源,提高程序的性能,该做事的时候做事,该休息的时候休息。
   
   二:RunLoop与线程
    
   (1)每条线程都有唯一的一个与之对应的RunLoop对象。
   (2)主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。
   (3)RunLoop在第一次获取时创建,在线程结束时候销毁。
   三:RunLoop相关类
   Core Foundation中关于RunLoop的5个类
   1:CFRunLoopRef
   2:CFRunLoopModeRef  ,CFRunLoopModeRef代表RunLoop的运行模式,一个RunLoop包含若干个运行模式,即一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer,每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode,如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入。系统默认注册了5个Mode:
   (1)kCFRunLoopDefaultMode:App的默认的Mode,通常线程是在这个Mode下运行
   (2)UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其它Mode影响
   (3)UIInitializationRunLoopMode:在刚启动App时进入的第一个Mode,启动完成后就不再使用
   (4)GSEventReceiveRunLoopMode:接收系统事件的内部Mode,通常用不到。
   (5)kCFRunLoopCommonMode:这是一种占位用的Mode,不是一种真正的Mode。
   3:CFRunLoopTimerRef
   (1)CFRunLoopTimerRef是基于时间的触发器。
   (2)基本上说的就是NSTimer,它会受到runloop的Mode的影响。
   (3)GCD的定时器不受RunLoop的mode的影响。
   关于定时器和runloopMode的关系如下代码
   
   ?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109////   ViewController.m//  CFRunLoopTimerRef////  Created by fe on  2016/10/25.//  Copyright © 2016年 fe. All rights reserved.// #import  "ViewController.h" @interface ViewController ()@property  (nonatomic , strong) dispatch_source_t timer;@end @implementation  ViewController -(void)touchesBegan:(NSSet<uitouch> *)touches  withEvent:(UIEvent *)event{         [self  GCDTimer]; }  -(void)timer1{    /*     第一种定时器用法,这种方式创建的定时器,     系统默认添加到NSRunLoop中的NSDefaultRunLoopMode模式中,     但是当用户和应用交互发生触摸滑动等事件时,     RunLoop的模式会切换到UITrackingRunLoopMode,     此时定时器就不再工作,因为定时器只在,默认被添加到的NSDefaultRunLoopMode     模式下工作。     */    [NSTimer  scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(go)  userInfo:nil  repeats:YES];}-(void)timer2{    /*     第二种定时器用法,这种方式创建的定时器,如果添加到NSRunLoop,     并设置RunLoop模式为NSDefaultRunLoopMode,     当用户和应用交互发生触摸滑动等事件时,     RunLoop的模式会切换到UITrackingRunLoopMode,     此时定时器就不再工作,因为定时器只在NSDefaultRunLoopMode模式下工作。           如果把用这种方式创建的定时器,添加到NSRunLoop,     并设置RunLoop模式为UITrackingRunLoopMode,     在这种情况下,只有当用户和应用交互发生触摸滑动等事件时,     定时器才会工作。           为了解决以上两种RunLoop运行模式造成的定时器,定时不准的问题。     我们可以把定时器添加到RunLoop并设置运行模式为NSRunLoopCommonModes.     在这种运行模式下,不管是默认状态,还是当用户和应用交互发生触摸滑动等事件时。     定时器都可以正常工作。     */    //1:创建定时器    NSTimer  *timer = [NSTimer timerWithTimeInterval:2.0 target:self  selector:@selector(go) userInfo:nil  repeats:YES];         //2.1:把定时器添加到RunLoop中,定时器在NSDefaultRunLoopMode模式下工作。    //[[NSRunLoop  currentRunLoop] addTimer:timer  forMode:NSDefaultRunLoopMode];         //2.2:把定时器添加到RunLoop中,定时器在UITrackingRunLoopMode模式下工作。    //[[NSRunLoop  currentRunLoop] addTimer:timer  forMode:UITrackingRunLoopMode];         //2.3    /*     把定时器添加到RunLoop中,设置模式为NSRunLoopCommonModes,     定时器在UITrackingRunLoopMode模式和NSDefaultRunLoopMode模式下都工作。           NSRunLoopCommonModes是一种标记模式,被打上这种标记的模式有以下两种     0  : contents = "UITrackingRunLoopMode"     2  : contents =  "kCFRunLoopDefaultMode"     */    [[NSRunLoop  currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];    NSLog(@"---------%@",[NSRunLoop  currentRunLoop]);      }-(void)GCDTimer{    /*     使用GCD的定时器,不会受到RunloopMode的影响。     */              //0:创建队列    dispatch_queue_t  queue = dispatch_queue_create("cn.520.www",  DISPATCH_QUEUE_CONCURRENT);         //1:创建一个GCD定时器    dispatch_source_t  timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,  queue);    self.timer =  timer;         //2:设置定时器的开始时间,间隔时间,精确度。精准度一般填0,表示没有误差。    dispatch_source_set_timer(timer,  DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 *  NSEC_PER_SEC);         //3:定时器要调用的方法。    dispatch_source_set_event_handler(timer,  ^{        NSLog(@"----------%@",[NSThread  currentThread]);    });         //4:启动定时器。    dispatch_resume(timer);}-(void)go{    NSLog(@"-----------");}@end</uitouch>
   
    
   4:CFRunLoopSourceRef
   (1)CFRunLoopSourceRef是事件源(输入源),分为两种。
   (2)Source0:非基于Port的,用于用户主动触发的事件。
   (3)Source1:基于Port的,通过内核和其它线程相互发送消息。
   5:CFRunLoopObserverRef
   (1)CFRunLoopObserverRef是观察者,能够监听RunLoop状态的改变。
   (2)可以监听的时间点有一下几个
   
   ?12345678910<span style="font-size:14px;">/* Run Loop  Observer Activities */    typedef  CF_OPTIONS(CFOptionFlags, CFRunLoopActivity)  {        kCFRunLoopEntry = (1UL  <<  0),//即将进入loop        kCFRunLoopBeforeTimers  = (1UL << 1),//即将处理timer        kCFRunLoopBeforeSources  = (1UL <<  2),//即将处理Source        kCFRunLoopBeforeWaiting  = (1UL <<  5),//即将进入休眠        kCFRunLoopAfterWaiting  = (1UL <<  6),//即将从休眠中唤醒        kCFRunLoopExit =  (1UL <<  7),//即将推出RunLoop        kCFRunLoopAllActivities  = 0x0FFFFFFFU//监听所有状态    };</span>
   和CFRunLoopObserverRef相关的代码如下:
   
   ?1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253-(void)observer{    /*     第一个参数:开辟内存空间     第二个参数:监听runloop的什么事件     第三个参数:是否持续监听     第四个参数:优先级     第五个参数:回掉     */    CFRunLoopObserverRef  observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),  kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer,  CFRunLoopActivity activity)  {                 switch  (activity){           case  kCFRunLoopEntry:                NSLog(@"--runloop即将进入循环--");                break;                             case  kCFRunLoopBeforeTimers:                NSLog(@"--runloop将要处理timer--");                break;                             case  kCFRunLoopBeforeSources:                NSLog(@"--runloop将要处理sources--");                break;                             case  kCFRunLoopBeforeWaiting:                NSLog(@"--runloop将要进入休眠--");                break;                             case  kCFRunLoopAfterWaiting:                NSLog(@"--runloop休眠结束即将进入循环--");                break;                             case  kCFRunLoopExit:                NSLog(@"--runloop退出循环--");                break;                             default:                break;        }         });                   /*     第一个参数:要监听哪一个runloop     第二个参数:监听者     第三个参数:要监听runloop在哪种运行模式下的状态     */    CFRunLoopAddObserver(CFRunLoopGetCurrent(),  observer, kCFRunLoopDefaultMode);     }
   
   
    
    
    
    
    
        

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程