RunLoop由来
- 线程在处理完自己的任务后一般会退出,为了实现线程不退出能够随时处理任务的机制被称为EventLoop,在iOS中就被称为RunLoop
Runloop的作用:
- 保持程序持续运行:例如程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的 RunLoop , RunLoop 保证主线程不会被销毁,也就保证了程序的持续运行;
- 处理 App 中的各种事件(比如:触摸事件,定时器事件,Selector事件等 );
- 节省CPU资源,优化程序性能:程序运行起来时,当什么操作都没有做的时候,RunLoop就通知系统,现在没有事情做,然后进行休息待命状态,这时系统就会将其资源释放出来去做其他的事情。当有事情做,也就是一有响应的时候RunLoop就会立马起来去做事情;
RunLoop与线程的关系
- 每条线程都有且只有一个与之对应的 RunLoop 对象(RunLoop 跑圈的原理就是一个 do-while 的阻塞线程的循环,因此不可能在同一线程中同时有两个RunLoop); 线程和RunLoop是一一对应的,关系保存在全局的字典里。
- RunLoop 在第一次获取时创建,在线程结束时会被销毁;只能在一个线程中获取自己和主线程的RunLoop。 主线程的 RunLoop 系统默认启动,子线程的 RunLoop 需要主动开启。 在主线程中,程序启动时,系统默认添加了有kCFRunLoopDefaultMode 和 UITrackingRunLoopMode两个预置Mode的RunLoop,保证程序处于等待状态,如果接收到来自触摸事件等,就会执行任务,否则处于休眠中。
- 线程创建时并没有RunLoop,(主线程除外),RunLoop不能创建,只能主动获取才会有。RunLoop的创建是在第一次获取时,RunLoop的销毁是发生在线程结束时。
实践
让子线程一直存在;正常情况下子线程执行完任务之后就会被销毁,通过加入循环让子线程一直保存
#pragma mark - 常驻线程
- (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");
}
tableView延迟加载图片的新思路
- (void)imageViewLoad{
//ImageView的显示 滑动时不加载 只在NSDefaultRunLoopMode模式下显示图片
UIImageView *img;
[img performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
}
RunLoop - 在一段时间内每隔一会执行某种任务的线程
//Run Loop 有 [acceptInputForMode:beforeDate:] 和[runMode:beforeDate:]方法来指定在一时间之内运行模式。如果不指定时间,Run Loop默认会运行在Default模式下(不断重复调用runMode:NSDefaultRunLoopMode beforeDate:...) 例如需要在应用启动之后,在一定时间内持续更新某项数据。
-(void)loopEvent{
@autoreleasepool {
//在30分钟内,每隔30s执行 run 方法
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
NSTimer * udpateTimer = [NSTimer timerWithTimeInterval:30
target:self
selector:@selector(run) userInfo:nil
repeats:YES];
[runLoop addTimer:udpateTimer forMode:NSRunLoopCommonModes];
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:60*30]];
}
}
网友评论