我正在使用以下代码来检索一些消息并将它们放入我的收件箱中。
MyInboxVC *inboxVC=[MyInboxVC get ];
//upload all the pending messages
UINavigationController *devNavController=[[MyappMgr get]getDeveloperNavigationController ];
[devNavController pushViewController:inboxVC animated:YES];
[devNavController setNavigationBarHidden:NO];
我得到了例外
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Pushing the same view controller instance more than once is not supported (<MyInboxVC: 0x1452a0>)'
这是什么意思?我做错了什么?
我相信当你非常快地执行某些操作时,这种情况也会发生。我构建了这样的东西:
if(![self.navigationController.topViewController isKindOfClass:[YOURCLASS class]]) {
首先处理崩溃,这样它就不会杀死你的应用程序:
@try {
[self.navController pushViewController:viewController animated:NO];
} @catch (NSException * e) {
NSLog(@"Exception: %@", e);
} @finally {
//NSLog(@"finally");
}
如果出现错误,请使用 popTo
- (void)pushViewController:(UIViewController *)viewController {
if (viewController) {
@try {
[self.navController pushViewController:viewController animated:NO];
} @catch (NSException * ex) {
//“Pushing the same view controller instance more than once is not supported”
//NSInvalidArgumentException
NSLog(@"Exception: [%@]:%@",[ex class], ex );
NSLog(@"ex.name:'%@'", ex.name);
NSLog(@"ex.reason:'%@'", ex.reason);
//Full error includes class pointer address so only care if it starts with this error
NSRange range = [ex.reason rangeOfString:@"Pushing the same view controller instance more than once is not supported"];
if ([ex.name isEqualToString:@"NSInvalidArgumentException"] &&
range.location != NSNotFound) {
//view controller already exists in the stack - just pop back to it
[self.navController popToViewController:viewController animated:NO];
} else {
NSLog(@"ERROR:UNHANDLED EXCEPTION TYPE:%@", ex);
}
} @finally {
//NSLog(@"finally");
}
} else {
NSLog(@"ERROR:pushViewController: viewController is nil");
}
}
表示从
ViewController
返回的[MyInboxVC get]
已经在devNavController
的导航栈中了。您不能多次将同一个对象添加到堆栈中。
显然,您之前已经推送了
MyInboxVC
。确保不再需要时将其弹出。
这就是“这是什么意思”的答案,但没有足够的信息来知道您需要做什么来解决它。
我的猜测是您的导航堆栈变得比您预期的要大,这意味着您没有像您应该的那样经常弹出。
您是否将此作为 segue 的一部分执行?如果是,则无需将 VC 推送到导航控制器上,因为 segue 已经执行此操作了。这就是你的错误发生的原因 - 你正在推送一个已经在 NavController 堆栈上的 VC。
这意味着当相同的视图控制器对象已经存在时,您将再次将其推送到堆栈。
[self.navigationController pushViewController:viewControllerObj animated:NO];
[self.navigationController pushViewController:viewControllerObj animated:NO];
检查您是否推入了循环,或者您是否不小心多次放置了代码..
这个问题的主要原因,显然是如果多次调用推送视图控制器的代码。发生这种情况的原因有很多,最常见的错误是从后台线程触发回调方法时,该方法在仍在推送视图控制器时可能会多次执行。 例子: 点击按钮时在后台线程上调用服务 api,这将允许您多次按下按钮,因此推送视图控制器的回调会被多次调用。 只要您不想通过多次推送来解决原始问题,@Melvin 和 @Sam 解决方案就是有效的。
这是 UINavigationController 的预期行为,当尝试推送堆栈中已经存在的视图控制器时会抛出异常(从 iOS 2.2 开始)。
这种情况发生在我身上,因为点击栏按钮发生得太快,并且很难重现,除非你对按钮点击感到疯狂。 下面通过禁用按钮,启动导航推送,然后在主线程上启用按钮来修复它(因为它会在推送动画发生后被调用)。
- (void)showMore
{
self.navigationItem.leftBarButtonItem.enabled = NO;
[self.navigationController pushViewController:moreVC animated:YES];
[self.navigationItem.leftBarButtonItem performSelectorOnMainThread:@selector(setEnabled:) withObject:@(YES) waitUntilDone:NO];
}
确保您没有在导航堆栈中添加视图控制器两次。 例如 - 在下面的示例中, self.mainViewC 被推送两次,因为它最初是在 navController 中实例化的,然后在最后一行再次推送到 navController 上,这会导致此问题。
navController=[[UINavigationController alloc] initWithRootViewController:self.mainViewC];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
[navController pushViewController:self.mainViewC animated:NO];
在这种情况下,当编写 initWithRootViewController 时,mainViewC 已经被添加到堆栈中。不再需要pushViewController。
在我的例子中,我正在推送一个视图控制器,但随后也尝试清除导航堆栈,以便在这个新的 VC 显示后没有 VC 可以弹出
self.show(viewController, sender: nil)
if clearNavigationStack {
self.navigationController?.viewControllers = [viewcontroller]
}
你不能在推送视图控制器后直接执行此操作,你需要等到视图控制器完全显示后再尝试重置导航堆栈
我经历过的另一个选择是 [MyInboxVC get ] 根本不返回 MyInboxVC 对象的实例。一个明显的迹象是错误显示“不支持多次推送相同的视图控制器实例(notTheInboxVC:0x9e31660)”,即。多次推送的类不是 MyInboxVC 预期的(未分配 MyInboxVC 的失败)
我使用 IB segue 修复了相同的问题(Swift 4):
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return navigationController?.topViewController is MainController ? true : false
}
就我而言,我正在推动视图控制器,然后尝试在此之后立即设置导航堆栈视图控制器数组。因此,它导致转换时随机崩溃(有时崩溃,有时不崩溃):
navigationController?.pushViewController(newViewController, animated: true)
navigationController?.viewControllers = [newViewController]
我需要做的是使用单行而不是这两行(https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621861-setviewcontrollers):
navigationController?.setViewControllers([newViewController], animated: true)
在显示之前检查您的控制器是否不等于
topViewController
的当前 navigationController
,在大多数情况下都有效。
但是,如果您的控制器可以在
navigationController
的堆栈上添加另一个控制器,则最好在显示您的控制器之前使用此检查:
if navigationController?.viewControllers.contains(controller) == false {
navigationController?.show(controller, sender: self)
}
[devNavController PushViewController:inboxVC 动画:NO]; 将动画设置为NO