RunLoop

RunLoop的实质是一个死循环,用于保证程序的持续运行,只有当程序退出的时候才会结束

1。保证线程的长时间存活
2。处理App中的各种事件(触摸、定时器、Selector事件)
3。节省CPU资源,提高程序性能(该做事做事,没事做休息)

RunLoop相关类:
CFRunLoopRef:代表RunLoop的对象
CFRunLoopModeRef:RunLoop的运行模式
CFRunLoopSourceRef:就是RunLoop模型图中提到的输入源/事件源
CFRunLoopTimerRef:就是RunLoop模型图中提到的定时源
CFRunLoopObserverRef:观察者,能够监听RunLoop的状态改变

RunLoop模式常用有3个:
NSDefaultRunLoopMode->默认模式,主线程中默认是NSDefaultRunLoopMode
UITrackingRunLoopMode->视图滚动模式,RunLoop会处于该模式下
NSRunLoopCommonModes->并不是真正意义上的Mode,是一个占位用的“Mode”,默认包含了NSDefaultRunLoopMode和UITrackingRunLoopMode两种模式

runloop和线程的关系:

主线程Runloop已经创建好了,子线程的runloop需要手动创建 ;一条线程对应一个RunLoop对象,每条线程都有唯一一个与之对应的RunLoop对象。一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出

runloop的实际使用:

1。RunLoop运行模式对NSTimer定时器的影响。

NSTimer的定时器是受运行模式影响的,而开发中我们有时候彻底去除这种影响,很显然,NSTimer定时器不能做到这点,这时,我们可以使用GCD的定时器。

2。ImageView推迟显示-->实现图片加载性能优化

当界面中含有UITableView,而且每个UITableViewCell里边都有图片。这时候当我们滚动UITableView的时候,如果有一堆的图片需要显示,那么可能会出现卡顿的现象。
2.1. 监听UIScrollView的滚动
因为UITableView继承自UIScrollView,所以我们可以通过监听UIScrollView的滚动,实现UIScrollView相关delegate即可。
2.2. 利用PerformSelector设置当前线程的RunLoop的运行模式
利用 performSelector 方法为UIImageView调用 setImage: 方法,并利用 inModes 将其设置为RunLoop下NSDefaultRunLoopMode运行模式。

[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"tupian"] afterDelay:4.0 inModes:NSDefaultRunLoopMode];

这样我们就实现了在拖动完之后,在延迟显示UIImageView。

3。后台常驻线程

我们在开发应用程序的过程中,如果后台操作特别频繁,经常会在子线程做一些耗时操作(下载文件、后台播放音乐等),我们最好能让这条线程永远常驻内存。

- (void)viewDidLoad {
    [super viewDidLoad];
    // 创建线程,并调用run1方法执行任务
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(run1) object:nil];
    [self.thread start];
}

- (void) run1{
    NSLog(@"----run1-----");
    // 添加下边两句代码,就可以开启RunLoop,之后self.thread就变成了常驻线程,可随时添加任务,并交于RunLoop处理
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
    // 测试是否开启了RunLoop,如果开启RunLoop,则来不了这里,因为RunLoop开启了循环。
    NSLog(@"未开启RunLoop");
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    // 利用performSelector,在self.thread的线程中调用run2方法执行任务
    [self performSelector:@selector(run2) onThread:self.thread withObject:nil waitUntilDone:NO];
}

- (void) run2{
    NSLog(@"----run2------");
}

经过运行测试,除了之前打印的 ----run1----- ,每当我们点击屏幕,都能调用 ----run2------ 。
这样我们就实现了常驻线程的需求。

4。runloop监听
5。runloop实现卡顿检测器

你可能感兴趣的:(RunLoop)