1、 Runloop
RunLoop RunLoop RunLoop RunLoop RunLoop对象 RunLoop资料 运行结构(RunLoop处理逻辑-官方版) RunLoop处理逻辑2、RunLoop与线程
RunLoop与线程#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//OC语言的API
//01 获得主线程对应的runloop对象 主运行循环
NSRunLoop *mainRunloop = [NSRunLoop mainRunLoop];
//NSLog(@"%@",mainRunloop);
//02 获得当前的runloop对象
NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop];
// NSLog(@"%p---%p",currentRunloop,mainRunloop);
//C语言的API
//01 主运行循环
CFRunLoopRef mainRunloopRef = CFRunLoopGetMain();
//02 当前的运行循环
CFRunLoopRef currentRunloopRef = CFRunLoopGetCurrent();
NSLog(@"%p-%p",mainRunloopRef,currentRunloopRef);
//转换
NSLog(@"%p-%p",mainRunloop.getCFRunLoop,mainRunloopRef);
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
}
-(void)run{
NSLog(@"run---%@",[NSThread currentThread]);
//子线程调用
//NSLog(@"%@",[NSRunLoop currentRunLoop]);
//runloop和线程的关系
//(1) 一一的对应的关系(字典)
//(2) 主线程对应的runloop默认已经创建并且开启了,而子线程对应的runloop需要手动创建并开启
//(3) 线程销毁,那么runloop也将销毁
//获得子线程对应的runloop |currentRunLoop该方法本身是懒加载的,如果是第一调用那么会创建当前线程对应的runloop并保存,以后调用则直接获取
NSRunLoop *newThreadRunloop = [NSRunLoop currentRunLoop];
NSLog(@"%@",newThreadRunloop);
[newThreadRunloop run]; //开启runloop (该runloop开启后马上退出了)
}
@end
3、RunLoop相关类
RunLoop相关类 RunLoop运行模式 RunLoop运行模式 几种运行模式----------------------RunLoop运行模式和Timer------------------------
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self performSelectorInBackground:@selector(timer2) withObject:nil];
}
-(void)timer1
{
//01 创建定时器对象
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
//02 添加到runloop中
//Mode :runloop的运行模式(5-默认|界面跟踪|占位)
//把定时器对象添加到runloop中,并指定运行模式为默认:(只有当运行模式为NSDefaultRunLoopMode的时候,定时器才会工作)
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
//当滚动textView的时候,主运行循环会切换运行模式(默认->界面追踪运行模式)
//把定时器对象添加到runloop中,并指定运行模式为界面跟踪:(只有当运行模式为NUITrackingRunLoopMode的时候,定时器才会工作)
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
//要求不管有没有在滚动控件,定时器都能够正常工作
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
//把定时器对象添加到runloop中,并指定运行模式为commonModes:
//只有当运行模式为被标记为commonModes的运行模式的时候,定时器才会工作
//被标记为commonModes运行模式:UITrackingRunLoopMode | kCFRunLoopDefaultMode
/*
common modes = <CFBasicHash 0x7fa4c9d00d70 [0x10a3f17b0]>{type = mutable set, count = 2,
entries =>
0 : <CFString 0x10b2ed270 [0x10a3f17b0]>{contents = "UITrackingRunLoopMode"}
2 : <CFString 0x10a411b60 [0x10a3f17b0]>{contents = "kCFRunLoopDefaultMode"}
}*/
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
-(void)timer2
{
NSLog(@"timer++++++%@",[NSThread currentThread]);
//定时器工作
//该方法内部会自动将创建的定时器对象添加到当前的runloop,并且指定运行模式为默认
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
//为了保证滑动textView时,定时器继续工作,需要知道运行模式为占位模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//手动创建子线程对应的runloop
[[NSRunLoop currentRunLoop] run];
}
-(void)run
{
NSLog(@"run----%@",[NSRunLoop currentRunLoop].currentMode);
}
4、GCD中的定时器
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//NSTimer中的定时器工作会受到runloop运行模式的影响
//GCD中的定时器是精准的,不受影响
//01 创建定时器对象
/* 参数说明
*
* 第一个参数:source的类型 DISPATCH_SOURCE_TYPE_TIMER 定时器leixing
* 第二个参数:对第一个参数的描述
* 第三个参数:更详细的描述
* 第四个参数:队列(GCD-4) 决定代码块(event_handler)在哪个线程中执行(串行队列-主线程|并发主队列-子线程)
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
//02 设置定时器(开始时间|调用间隔|精准度)
/* 参数说明
*
* 第一个参数:定时器对象
* 第二个参数:开始计时的时间 DISPATCH_TIME_NOW 现在开始
* 第三个参数:间隔时间
* 第四个参数:精准度(允许的误差)
*/
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//03 事件回调(定时器执行的任务)
dispatch_source_set_event_handler(timer, ^{
NSLog(@"GCD---%@",[NSThread currentThread]);
});
//04 启动定时器
dispatch_resume(timer);
//05 添加一个引用
self.timer = timer;
}
@end
5、CFRunLoopSourceRef
CFRunLoopSourceRef就是inputSource 函数调用栈总结:
注意:
1、有线程不一定有RunLoop,但有RunLoop就必须有线程
2、线程销毁或者给runloop设定的时间到的话runloop就会退出
6、CFRunLoopObserverRef
CFRunLoopObserverRef-------------------------RunLoopObserverRef的使用------------------------
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
/**01 创建观察者对象
*参数说明:
*allocator 分配存储空间(默认)
*activities 需要监听runloop的状态
*repeats 是否持续监听 yes
*order 0
*/
/**CFRunLoopObserverRef ob = CFRunLoopObserverCreateWithHandler(CFAllocatorRef allocator, CFOptionFlags activities, Boolean repeats, CFIndex order, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
})
*/
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
/*运行状态:
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5),
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
*/
switch (activity) {
case kCFRunLoopEntry:
NSLog(@"runloop即将进入");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"即将处理timer事件");
break;
case kCFRunLoopBeforeSources:
NSLog(@"即将处理source事件");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"即将进入休眠");
break;
case kCFRunLoopAfterWaiting:
NSLog(@"被唤醒");
break;
case kCFRunLoopExit:
NSLog(@"runloop退出");
break;
default:
break;
}
});
/*02 监听当前runloop的运行状态
*参数说明
*
*第一参数:runloop对象
*第二参数:监听者
*第三参数:监听runloop在哪种运行模式下的状态
*/
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
[NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
}
-(void)timerRun
{
NSLog(@"处理收到的事件--timer--RUN");
}
7、代码模拟RunLoop死循环
#import <Foundation/Foundation.h>
void msg(int n){
NSLog(@"runloop被唤醒");
NSLog(@"runloop处理%d这个任务",n);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"runloop启动啦");
do {
NSLog(@"runloop即将处理timer事件");
NSLog(@"runloop即将处理source事件");
NSLog(@"还有事件响应我来处理吗?");
NSLog(@"runloop进入到休眠");
int number = 0;
scanf("%d",&number);
msg(number);
} while (1);
}
return 0;
}
8、RunLoop的应用
runloop应用- 应用01
- 应用02
网友评论