iOS中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef
CFRunLoopRef是在CoreFoundation框架内的,它提供了纯C函数的API,所有这些API都是线程安全的,代码是开源的。
NSRunLoop是基于CFRunLoopRef的封装,提供了面向对象的API,但是这些API不是线程安全的。
RunLoop对外的接口
在CoreFoundation里面关于RunLoop有几个类:
CFRunLoop
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5),即将进行休眠
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
CFRunLoopSourceRef是事件产生的地方。
CFRunLoopTimerRef是基于时间的触发器
CFRunLoopObserverRef是观察者,
首先添加runloop观察者,这里是用纯c语言写的
#pragma mark--1
[NSThread mainThread] 获取主线程 [NSThread currentThread] 获取当前线程
//调用runloop底层设计,运行纯c代码写,可以直接拷贝到代码里用
[self addRunloopObserver];
//runLoop,解决拉动tableviewcell,顶部无线轮播不滚动等
//目的:
//1保证程序不退出
//2负责监听所有的时间,触摸(UI界面的处理),时钟,网络事件
//3 RunLoop 它还需要做UI的绘制,在一次tunloop循环中要绘制屏幕上有变化的所有的点
//NSDefaultRunLoopMode--时钟网络事件
// NSRunLoopCommonModes--用户交互(UI事件处理)
//方法一:UI处理优先级更高
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updataTimer) userInfo:nil repeats:YES];
//加入运行循环
[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updataTimer) userInfo:nil repeats:YES];
//注意在这里千万不要做耗时操作
-(void)updataTimer{
static int num = 0;
//如果出现耗时操作。导致和ui界面优先级一样,UI会出现偶尔卡顿
//打印当前线程
NSLog(@"%@ %d",[NSThread currentThread],num++);
}
#pragma mark--2
//解决问题:卡顿问题 分析:为什么会卡顿 一次runloop循环需要给绘制屏幕上所有的点,一次runloop需要绘制15张高清图片
/*思路
1 监听Runloop循环,C语言
2 在Runloop循环一次的时候,从数组里面拿到代码执行(数组是有长度的)
*/
//在viewdidload里面添加runloop观察者方法addRunloopObserver
//在cell里面添加addTask方法
[self addTask:^BOOL{
//将添加图片的代码写在block里面
return YES;
}];
#pragma mark --<关于runloop的方法和函数>
//添加任务的方法
-(void)addTask:(RunloopBack )unit{
[self.tasks addObject:unit];
//保证数组里面只有30个任务
if (self.tasks.count > self.maxQueueLength) {
[self.tasks removeObjectAtIndex:0];
}
}
-(void)addRunloopObserver{
//获取当前Runloop
CFRunLoopRef runloop =CFRunLoopGetCurrent();
//定义一个上下文
CFRunLoopObserverContext context = {
0,
(__bridge void*)self,
&CFRetain,
&CFRelease,
NULL
};
//定义观察者 CallBack是个回调函数
static CFRunLoopObserverRef defaultObserver ;
//创建观察者
defaultObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES,NSIntegerMax-999, &CallBack, &context);
//添加当前的runloop的观察者
CFRunLoopAddObserver(runloop, defaultObserver, kCFRunLoopDefaultMode);
//c语言有creat就需要release
CFRelease(defaultObserver);
}
//runloop回调函数
//从数组里面拿代码执行
static void CallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
ViewController * VC= (__bridge ViewController *)(info);
if (VC.tasks.count ==0) {
return;
}
BOOL result = NO;
while (result ==NO && VC.tasks.count) {
//取出任务
RunloopBack unit= VC.tasks.firstObject;
//执行任务
result = unit();
//干掉刚执行完毕的任务
[VC.tasks removeObjectAtIndex:0];
}
// NSLog(@"来了");
}