“不支持多次推送相同的视图控制器实例”例外

时间:2011-08-16 18:27:10

标签: iphone ios uiviewcontroller

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

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>)'

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

13 个答案:

答案 0 :(得分:69)

我相信当你快速做一些动作时,这也会发生。我像这样建立一些东西:

if(![self.navigationController.topViewController isKindOfClass:[YOURCLASS class]]) {

编辑//

这种情况更常发生在动画速度较慢的旧设备上,如iphone 3或3gs

答案 1 :(得分:20)

首先处理崩溃,这样它就不会杀死你的应用程序:

@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");
  }
}

答案 2 :(得分:7)

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

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

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

我的猜测是你的导航堆栈比你想象的要大得多,这意味着你没有像你想象的那样经常弹出。

答案 3 :(得分:5)

您是否将此作为segue的一部分执行?如果是,则无需将VC推送到导航控制器上,因为segue已经执行此操作。这就是您的错误发生的原因 - 您正在推送已经在NavController堆栈上的VC。

答案 4 :(得分:4)

这意味着当它已经在那里时,你正在推动同一个viewcontroller对象再次堆叠。

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

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

检查你是否在循环中推进或者你是否意外地将代码放置了一次以上..

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

答案 7 :(得分:1)

This was happening to me on a bar button click happening too fast, and was hard to reproduce, unless you went nuts on the button taps. The following fixed it by disabling the the button, starting the nav push, then enabling the button on the main thread (because it would be called after animation from the push occurred).

- (void)showMore
{
    self.navigationItem.leftBarButtonItem.enabled = NO;
    [self.navigationController pushViewController:moreVC animated:YES];
    [self.navigationItem.leftBarButtonItem performSelectorOnMainThread:@selector(setEnabled:) withObject:@(YES) waitUntilDone:NO];
}

答案 8 :(得分:1)

确保您没有在导航堆栈中添加两次视图控制器。 例如 - 在下面的示例中,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了。

答案 9 :(得分:0)

我遇到的另一个选项是[MyInboxVC get]根本没有返回MyInboxVC对象的实例。一个告诉故事的标志是错误是说'不支持多次推送相同的视图控制器实例(notTheInboxVC:0x9e31660)'即。被推送不止一次的类不是预期的MyInboxVC(从MyInboxVC没有被分配掉)

答案 10 :(得分:0)

我使用以下方法修复了与IB segue相同的问题(Swift 4):

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

答案 11 :(得分:0)

在我的情况下,我正在推动一个Viewcontroller,但随后还尝试清除导航堆栈,以便在显示此新的VC之后没有VC弹出

self.show(viewController, sender: nil)

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

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

答案 12 :(得分:-1)

[devNavController pushViewController:inboxVC animated:NO]; 将动画设置为NO