Iphone &引用;不支持多次推送同一视图控制器实例";例外

Iphone &引用;不支持多次推送同一视图控制器实例";例外,iphone,ios,uiviewcontroller,Iphone,Ios,Uiviewcontroller,我正在使用以下代码检索一些邮件并将它们放入我的收件箱 MyInboxVC *inboxVC=[MyInboxVC get ]; //upload all the pending messages UINavigationController *devNavController=[[MyappMgr get]getDeveloperNavigationController ]; [devNavController pushViewController:inboxVC animated:YES];

我正在使用以下代码检索一些邮件并将它们放入我的收件箱

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>)'
由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“不支持多次推送同一视图控制器实例()”

这是什么意思?我做错了什么?

这意味着从
[MyInboxVC get]
返回的
ViewController
已经在
devNavController
的导航堆栈中。不能多次将同一对象添加到堆栈中

显然,您之前已经推送了一个
MyInboxVC
。确保您在不再需要它时将其弹出

这就是“这是什么意思”的答案,但是没有足够的信息知道你需要做什么来修复它


我猜您的导航堆栈比预期的要大,这意味着您没有像预期的那样频繁弹出。

这是UINavigationController的预期行为,在尝试推送堆栈中已经存在的视图控制器时会引发异常(它来自iOS 2.2)

我相信,当你快速采取一些行动时,这种情况也会发生。我构建了这样的东西:

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对象再次推入堆栈,而该对象已在其中

[self.navigationController pushViewController:viewControllerObj animated:NO];

[self.navigationController pushViewController:viewControllerObj animated:NO];

检查是否在循环内推送或是否多次意外放置代码。

我遇到的另一个选项是[MyInboxVC get]根本不返回MyInboxVC对象的实例。这方面的一个明显迹象是,错误是“不支持多次推送同一视图控制器实例(notTheInboxVC:0x9e31660)”。即,被推送多次的类不是预期的MyInboxVC(未分配MyInboxVC的失败)

此问题的主要原因,显然,如果推送视图控制器的代码被多次调用。出现这种情况的原因有很多,最常见的错误是从后台线程触发回调方法,在后台线程中,当回调方法仍在推送视图控制器时,可以多次执行该方法。 例子: 点击按钮时在后台线程上调用服务api,这将允许您多次按下按钮,因此推动视图控制器的回调将被多次调用。
@Melvin和@Sam解决方案是有效的,只要您不想通过多次按下来修复原始问题

您是否将此作为一个序列的一部分执行?如果你是,就没有必要把VC推到你的导航控制器上,因为segue已经可以这样做了。这就是发生错误的原因-您正在推一个已经在NavController堆栈上的VC。

[devNavController-pushViewController:inboxVC-animated: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

我用IB segue修复了相同的问题(Swift 4),使用:

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    return navigationController?.topViewController is MainController ? true : false 
}

在我的例子中,我正在推一个viewcontroller,但同时也试图清除导航堆栈,这样在这个新的vc出现后就没有vc可以弹出了

self.show(viewController, sender: nil)

if clearNavigationStack {
    self.navigationController?.viewControllers = [viewcontroller]
}

您不能在按下viewcontroller后直接执行此操作,您需要等到viewcontroller完全显示后再尝试重置导航堆栈

我在一个非常简单的应用程序中遇到了相同的问题。这帮我解决了问题。我有这张支票,但例外情况仍然存在。第二次推送时,topViewController尚未更改。如果我在没有动画的情况下推,它会工作。有人能帮忙吗?这是“修复”症状,而不是根本原因。我也有同样的问题,尝试添加try,catch block,但它从未进入catch block。我是不是漏掉了什么?在循环中。它起作用了,谢谢。
self.show(viewController, sender: nil)

if clearNavigationStack {
    self.navigationController?.viewControllers = [viewcontroller]
}