目录
前言
1.performSelector相关的一个问题
2.一个崩溃问题
前言
记录GCD使用过程中遇到的一个小问题。
1.performSelector相关的一个问题
输入下面代码的打印结果:
- (void)viewDidLoad {
[super viewDidLoad];
[self gcdDemos01];
}
- (void)gcdDemos01{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"do task1");
[self performSelector:@selector(test) withObject:nil afterDelay:0];
NSLog(@"do task3");
});
}
- (void)test{
NSLog(@"do task2");
}
想一下运行之后控制台如何输出:
图1.GCD控制台打印结果
这里的
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
的底层其实是往Runloop中添加了一个定时器,但是默认情况下子线程中的RunLoop是没有启动的。
这里如果想要执行test方法,则需要我们手动启动RunLoop。
修改之后的代码如下:
[super viewDidLoad];
[self gcdDemos01];
}
- (void)gcdDemos01{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"do task1");
[self performSelector:@selector(test) withObject:nil afterDelay:0];
NSLog(@"do task3");
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc]init] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
});
}
- (void)test{
NSLog(@"do task2");
}
这个时候运行代码,控制台的打印信息如下:
图2.手动启动RunLoop
iOS中还有一个类似的方法,就是
- (id)performSelector:(SEL)aSelector withObject:(id)object;
这个方法底层就是基于Runtime实现的。调用的是msgSend方法。
我们把上述代码中的方法替换一下,也可以实现test的方法的打印功能。
- (void)viewDidLoad {
[super viewDidLoad];
[self gcdDemos01];
}
- (void)gcdDemos01{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"do task1");
[self performSelector:@selector(test) withObject:nil];
NSLog(@"do task3");
});
}
- (void)test{
NSLog(@"do task2");
}
2.一个崩溃问题
看一下下面代码的打印结果:
- (void)test{
NSLog(@"do task2");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSThread * thread = [[NSThread alloc]initWithBlock:^{
NSLog(@"do task1");
}];
[thread start];
[self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}
仔细思考下你想象中的结果。
控制台打印如下:
图2.控制台输出结果
这里thread执行完打印任务之后,线程就退出了。退出之后,有在这个线程上执行了test方法,一次崩溃了。
解决的方案和第一个问题一样,我们手动启动下RunLoop即可。