Исключение «Вызов одного экземпляра контроллера представления более одного раза не поддерживается» - PullRequest
41 голосов
/ 16 августа 2011

Я использую следующий код для извлечения некоторых сообщений и помещения их в свой почтовый ящик.

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

Что это значит? Что я делаю не так?

Ответы [ 12 ]

69 голосов
/ 24 февраля 2012

Я верю, что когда вы выполняете какие-то действия очень быстро, это тоже может произойти. Я строю что-то вроде этого:

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

редактировать //

это происходит чаще на старых устройствах с медленной анимацией, таких как iphone 3 или 3gs

20 голосов
/ 14 мая 2012

Во-первых, обработайте сбой, чтобы он не убивал ваше приложение:

@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");
  }
}
7 голосов
/ 16 августа 2011

Это означает, что ViewController, возвращаемый из [MyInboxVC get], уже находится в стеке навигации devNavController.Вы не можете добавлять один и тот же объект в стек несколько раз.

Очевидно, у вас уже есть MyInboxVC, выдвинутый ранее.Убедитесь, что вы выдавили его, когда он больше не нужен.

Это ответ "что это значит", но у меня недостаточно информации, чтобы знать, что нужно сделать, чтобы исправить это.

Я думаю, ваш стек навигации становится больше, чем вы.ожидаете, что означает, что вы не высовываетесь так часто, как следовало бы.

5 голосов
/ 12 октября 2014

Вы выполняете это как часть segue?Если это так, нет необходимости вставлять виртуальный контроллер на ваш контроллер навигации, потому что Segue будет делать это уже.Вот почему возникает ваша ошибка - вы нажимаете VC, который уже находится в стеке NavController.

4 голосов
/ 29 июля 2013

Это означает, что вы снова помещаете один и тот же объект viewcontroller в стек, когда он уже там.

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

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

проверьте, не нажимаете ли вы внутри цикла или случайно разместили код более одного раза.

1 голос
/ 03 ноября 2015

Убедитесь, что вы не добавляете контроллер представления дважды в стек навигации. Например, в приведенном ниже примере self.mainViewC передается дважды, поскольку он первоначально создается в navController, а затем снова помещается в navController в последней строке, что может вызвать эту проблему.

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

В этом случае mainViewC уже был добавлен в стек, когда был написан initWithRootViewController. Больше нет необходимости в pushViewController.

1 голос
/ 30 июня 2015

Это происходило со мной из-за слишком быстрого нажатия кнопки, и его было трудно воспроизвести, если только вы не сошли с ума от нажатий кнопок.Следующее исправило это, отключив кнопку, запустив навигацию, затем включив кнопку в главном потоке (потому что она будет вызываться после того, как анимация произошла от нажатия).

- (void)showMore
{
    self.navigationItem.leftBarButtonItem.enabled = NO;
    [self.navigationController pushViewController:moreVC animated:YES];
    [self.navigationItem.leftBarButtonItem performSelectorOnMainThread:@selector(setEnabled:) withObject:@(YES) waitUntilDone:NO];
}
1 голос
/ 02 октября 2014

Основная причина этой проблемы, очевидно, если код, который выдвинул контроллер представления, вызывается более одного раза.Это может произойти по многим причинам, наиболее распространенная ошибка, когда метод обратного вызова запускается из фонового потока, где этот метод может выполняться более одного раза, пока он все еще проталкивает контроллер представления.Пример: вызов API-интерфейса службы в фоновом потоке при нажатии кнопки, который позволит вам нажимать кнопку более одного раза, и поэтому обратный вызов, который толкает контроллер представления, вызывается более одного раза.Решение @Melvin и @Sam действует до тех пор, пока вы не хотите исправить исходную проблему, не нажимая более одного раза.

1 голос
/ 16 августа 2011

Это ожидаемое поведение UINavigationController, при котором выдается исключение при попытке протолкнуть контроллер представления, который уже присутствует в стеке (он есть в iOS 2.2).

0 голосов
/ 04 января 2018

Я исправил ту же проблему (Swift 4) с помощью IB segue, используя:

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    return navigationController?.topViewController is MainController ? true : false 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...