我为了解决这个涉及推送视图控制器到导航控制器堆栈的问题破了一周的头。
问题是这样的:我正在使用基于导航控制的应用程序并且我有3个视图控制器,vA、vB和vC。
我正在使用以下方法从vA推送vB:
[self.navigationController pushViewController:vB animated:YES]
它起作用,但是当我试图从vB中推送vC时,vB的self.navigationController属性为nil,而且vB不在导航控制器堆栈上。什么?是的,我将vB推入了导航堆栈,并没有将其添加到其中,但即便如此,vB仍然正确显示。
我发现,在vB的viewDidLoad内部,self.navigationController不为nil,并且vB在导航控制器堆栈上,但是一旦vB的viewDidLoad结束,vB就会从导航控制器堆栈中移除,并且它的navigationController属性被设置为nil。此时,vB成为了一种幽灵控件,超出了导航控制器堆栈之外。
我不需要提到,从vB中,我无法返回vA或推送vC。
为什么会发生这种情况?
很简单,我是从一个块内部推送vB的,就像这样:
void (^ block1)() = ^(){
[self.navigationController pushViewController:vB animated:YES];
};
因为一个UIKit函数(推送功能)被执行在一个可能不是主线程的块中,所以发生了什么。
解决方法是将推送包装在分发到主线程的块中,使用以下代码:
void (^ block1)() = ^(){
dispatch_async(dispatch_get_main_queue(),
^{
[self.navigationController pushViewController:vB animated:YES];
});
};
该应用程序还有一个小问题,即错误的插座连接到了viewController,但这是主要问题。这种问题很难发现,因为它很微妙。当我向导航栏添加另一个按钮时,我才发现问题:该按钮没有显示。因此,我怀疑涉及UIKit的某些事情正在发生,或在那种情况下没有发生。这里的大问题是这份代码没有崩溃、没有错误消息,仅仅表现不佳,但是正常运行。
controllers
仅包含vcA? 你打印输出(NSLog)了吗? 仅通过调试器观察可能会误导。 - Eli Ganem