运行循环
- iOS多线程:『RunLoop』详尽总结
- 一条线程对应一个 RunLoop 对象,但除主线程外,其他线程都需要显示的创建和维护 RunLoop 对象
- 非主线程的 RunLoop 对象在第一次获取 RunLoop 时创建:
[NSRunLoop currentRunLoop]
使用场景
一:让 NSTimer 正常工作,不受 UIScrollView 滚动的影响而暂停
滚动UIScrollView
时,runloop
的模式会被切换到UITrackingRunLoopMode
,使timer
的循环被暂停,滚动停止后定时器又恢复正常。若想在滚动时timer
不受影响,可以把timer
添加到当前线程的运行循环,并且模式为NSRunLoopCommonModes
,代码如下:
1
2
3
4
5
6
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(test)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
二:性能优化
有时侯在快速滚动 tableView 时,希望滚动时不加载 cell 中的图片,滚动停止后再加载,提高界面流畅性。
示例代码:
1
2
// 拖动 UITextView 4秒以上,发现过了4秒之后,UIImageView 还没有显示图片,松开的时候,则显示图片
[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"tupian"] afterDelay:4.0 inModes:@[NSDefaultRunLoopMode]];
三:让线程常驻后台
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.thread start];
}
- (void) run {
// 这里写任务
NSLog(@"----run-----");
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
// 添加下边两句代码,开启 RunLoop,之后 self.thread 就成了常驻线程,可随时添加任务执行
// 注意要添加一个输入源 port
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
// [runLoop run];
// 在实际开发中最好使用这种方式来确保 runloop 能退出,做双重的保障
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(timeoutInterval + 5)]];
// 测试是否开启了 RunLoop:如果已经开启 RunLoop,则来不了这里,因为开启了循环。
NSLog(@"未开启RunLoop");
}
本文由作者按照 CC BY 4.0 进行授权