web-dev-qa-db-ja.com

「同じView Controllerインスタンスを複数回プッシュすることはサポートされていません」例外

次のコードを使用していくつかのメッセージを取得し、受信トレイに入れています。

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

どういう意味ですか?私は何を間違えていますか?

42
Suchi

あなたがいくつかのアクションを本当に速く行うと、これも起こりうると思います。私はこのようなものを構築します:

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

最初にクラッシュを処理して、アプリを強制終了しないようにします。

@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");
  }
}
20
brian.clear

これは、[MyInboxVC get]から返されたViewControllerが既にdevNavControllerのナビゲーションスタックにあることを意味します。同じオブジェクトをスタックに複数回追加することはできません。

どうやら、すでにMyInboxVCが以前にプッシュされています。不要になったときにポップしたことを確認してください。

これは「どういう意味ですか」という答えですが、修正するために何をする必要があるかを知るのに十分な情報がありません。

私の推測では、Navigation Stackは予想よりも大きくなっています。つまり、必要な頻度でポップしないということです。

7
MarkPowell

セグエの一部としてこれを実行していますか?もしそうなら、VCをNavigation Controllerにプッシュする必要はありません。セグエが既にそれを行うからです。それがエラーが発生している理由です-VCこれはすでにNavControllerのスタック上にあります。

5
micnguyen

それは、同じViewControllerオブジェクトをプッシュして、すでにそこにあるときに再びスタックすることを意味します。

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

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

ループ内にプッシュするか、誤ってコードを複数回配置したかどうかを確認してください。

4
Durai Amuthan.H

ナビゲーションスタックにView Controllerを2回追加しないようにしてください。たとえば、以下の例では、self.mainViewCは最初にnavControllerでインスタンス化され、最後の行で再度navControllerにプッシュされるため、2回プッシュされます。これにより、この問題が発生します。

  navController=[[UINavigationController alloc] initWithRootViewController:self.mainViewC];  
  self.window.rootViewController = navController;
  [self.window makeKeyAndVisible];        
  [navController pushViewController:self.mainViewC animated:NO]; 

この場合、initWithRootViewControllerが記述されたときにmainViewCがすでにスタックに追加されています。 pushViewControllerを再度必要とすることはありません。

1
Kavish

これは、ボタンのクリックが速すぎて私に起こっていたもので、ボタンのタップに夢中になっていない限り、再現するのは困難でした。以下は、ボタンを無効にしてnav Pushを開始し、メインスレッドでボタンを有効にすることで修正しました(プッシュからのアニメーションが発生した後に呼び出されるため)。

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

View Controllerをプッシュしたコードが複数回呼び出される場合、明らかにこの問題の主な理由。これは多くの理由で発生する可能性があります。最も一般的な間違いは、コールバックメソッドがバックグラウンドスレッドからトリガーされた場合です。例:ボタンをタップするときにバックグラウンドスレッドでサービスAPIを呼び出すと、ボタンを複数回押すことができるため、View Controllerをプッシュするコールバックが複数回呼び出されます。 @Melvinと@Samのソリューションは、2回以上プッシュしないことで元の問題を修正したくない限り有効です。

1
Elie

これは、スタックに既に存在するView Controllerをプッシュしようとすると例外がスローされるUINavigationControllerの予想される動作です(iOS 2.2から)。

1
Sivaprasad

以下を使用して、IBセグエの同じ問題(Swift 4)を修正しました。

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

私が経験した別のオプションは、[MyInboxVC get]がMyInboxVCオブジェクトのインスタンスをまったく返さないことです。このことは、「同じView Controllerインスタンスを2回以上プッシュすることはサポートされていません(notTheInboxVC:0x9e31660)」というエラーが表示されることを意味します。複数回プッシュされるクラスは、予想されるMyInboxVCではありません(MyInboxVCからのフォールスルーは割り当てられていません)

0
arcady bob