今天在面试的时候遇到个新手,谈到线程的时候,他说他经常在子线程进行页面跳转,代码类似如下这段,页面A按了按钮后跳转页面B。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
BViewController *bV = [sb instantiateViewControllerWithIdentifier:@"vb"];
[self presentViewController:bV animated:NO completion:^{
}];
});
嗯,在子线程中使用presentViewController:animated:completion:
,并且成功进行了页面跳转。
一般在子线程跳转页面代码会出现页面延迟加载,这是因为在子线程结束后主线程实现了子线程函数栈的原因,所以第一次遇到这居然能成功及时跳转还挺吃惊。经验告诉我,这段presentViewController:animated:completion:
虽然写在子线程里,但是真正进行页面跳转的应该还是在主线程中。
为了验证这个想法,给这段代码加上日志。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"queue 1 currentThread:%@",[NSThread currentThread]);
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
BViewController *bV = [sb instantiateViewControllerWithIdentifier:@"vb"];
[self presentViewController:bV animated:NO completion:^{
NSLog(@"queue 2 currentThread %@", [NSThread currentThread]);
}];
});
不出所料,得出的结果验证了我的想法,确实进入了主线程。
queue 1 currentThread:<NSThread: 0x60400026ff40>{number = 3, name = (null)}
queue 2 currentthread <NSThread: 0x600000066740>{number = 1, name = main}
那么为什么presentViewController:animated:completion:
可以在子线程中跳转呢?我用clang转化成C/C++代码,看看Runtime是不是可以暴露原因。
static void _I_ViewController_transitionView_(ViewController * self, SEL _cmd, id sender) {
dispatch_async(dispatch_get_global_queue(0, 0), ((void (*)())&__ViewController__transitionView__block_impl_1(
(void *)__ViewController__transitionView__block_func_1, &__ViewController__transitionView__block_desc_1_DATA, self, 570425344)));
}
emmmm.....完全看不出原因,看来iOS底层隐藏了。
iOS的模态试图跳转是通过消息传递的,所以猜测presentViewController:animated:completion:
的方式跳转界面,可能在底层就是主线程执行回调的。
网友评论