记录 仅供学习使用。
1. RunLoop在iOS中的落地使用细节
1.1 RunLoop和线程的关系
- 在默认情况下, 线程执行完之后就会退出, 就不能再继续任务了. 这时我们需要采用一种方式来让线程能够不断地处理任务, 并不退出. 所以, 我们就有了RunLoop.
- 一条线程对应一个RunLoop对象, 每条线程都有唯一一个与之对应的RunLoop对象.
- RunLoop并不保证线程安全. 我们只能在当前线程内部操作当前线程的RunLoop对象, 而不能在当前线程内部去操作其他线程的RunLoop对象方法.
- RunLoop对象在第一次获取RunLoop时创建, 销毁则是在线程结束的时候.
- 主线程的RunLoop对象系统自动帮助我们创建好了(
UIApplicationMain函数), 子线程的RunLoop对象需要我们主动创建和维护.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
1.1.1 RunLoop与常驻线程
- 常驻线程
- 指的就是那些不会停止,一直存在于内存中的线程。
- 后台常驻线程测试代码:
- (void)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<UITouch *> *)touches withEvent:(UIEvent *)event {
// 利用performSelector,在self.thread的线程中调用run2方法执行任务
[self performSelector:@selector(run2) onThread:self.thread withObject:nil waitUntilDone:NO];
}
- (void)run2 {
NSLog(@"----run2-----");
}