职坐标linux多线程与网络编程,IOS开发入门iOS 多线程编程(十五、RunLoop简单介绍)...

本文详细介绍了iOS中的RunLoop及其与多线程编程的关系,包括RunLoop的作用、线程与RunLoop的对应关系,以及RunLoop的五种核心类。重点讲解了RunLoop的运行模式对NSTimer的影响,并提供了代码示例进行解析。文章强调了正确配置RunLoopMode对于保证定时器准确触发的重要性,并提到了GCD定时器不受RunLoopMode影响的特点。
摘要由CSDN通过智能技术生成

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

1d8143e350e41516f29fc525e761115f.png

一:什么是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 *)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

4:CFRunLoopSourceRef

(1)CFRunLoopSourceRef是事件源(输入源),分为两种。

(2)Source0:非基于Port的,用于用户主动触发的事件。

(3)Source1:基于Port的,通过内核和其它线程相互发送消息。

5:CFRunLoopObserverRef

(1)CFRunLoopObserverRef是观察者,能够监听RunLoop状态的改变。

(2)可以监听的时间点有一下几个

?12345678910/* 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//监听所有状态    };

和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频道!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值