1、GCD和RunLoop一起使用
- 下面打印结果是什么?
- (void)test4 {
NSLog(@"3");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
dispatch_async(queue, ^{
NSLog(@"1");
[self performSelector:@selector(test4) withObject:nil afterDelay:0.0];
NSLog(@"2");
NSLog(@"--end");
});
}
打印结果:
2022-01-25 16:30:45.631871+0800 gcd[26764:2852276] 1
2022-01-25 16:30:45.632006+0800 gcd[26764:2852276] 2
2022-01-25 16:30:45.632075+0800 gcd[26764:2852276] --end
- 为什么任务3不打印呢?
因为[self performSelector:@selector(test4) withObject:nil afterDelay:0.0];这句代码是往RunLoop中添加了定时器,然而,全局队列下的异步函数是开启了一个子线程,子线程是默认不会开启RunLoop的,需要手动开启RunLoop
如下修改:
- (void)test4 {
NSLog(@"3");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
dispatch_async(queue, ^{
NSLog(@"1");
[self performSelector:@selector(test4) withObject:nil afterDelay:0.0];
NSLog(@"2");
[[NSRunLoop currentRunLoop] addPort:[[NSPort port] init] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSLog(@"--end");
});
}
打印结果:(没有打印end)
2022-01-25 16:35:47.531165+0800 gcd[26952:2855439] 1
2022-01-25 16:35:47.531317+0800 gcd[26952:2855439] 2
2022-01-25 16:35:47.531435+0800 gcd[26952:2855439] 3
2、NSThread和RunLoop
下面代码打印是什么?
- (void)test5 {
NSLog(@"5");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSLog(@"1%@",[NSThread currentThread]);
}];
[thread start];
[self performSelector:@selector(test5) onThread:thread withObject:nil waitUntilDone:YES];
}
执行完了任务1后,会崩溃,因为往子线程thread中再次添加任务的时候,子线程已经自动销毁了,线程没有被保活
解决方案,让线程保活!
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)test5 {
NSLog(@"5");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSLog(@"1%@",[NSThread currentThread]);
[[NSRunLoop currentRunLoop] addPort:[[NSMachPort port] init] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}];
[thread start];
[self performSelector:@selector(test5) onThread:thread withObject:nil waitUntilDone:YES];
}
Foundation框架源码学习:GNUStep:GNUstep: Download
也可以参考这个