Подтвердить что ты не робот

IOS: непредвиденное поведение popViewController

Я искал интернет для решения. Я ничего не смог найти. Так: Я использую UINavigationController. Я нажимаю на него два UIViewControllers. Во втором нажатом ViewController я выполняю этот код:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
NSLog([error localizedDescription]);
[self.navigationController popViewControllerAnimated:YES]; }

Ожидаемое, что произойдет, будет то, что последний нажатый ViewController исчезнет. В этом приложении я делаю это на нескольких местах, и он отлично работает везде, ожидаемый в этом самом ViewController. Случается, что только задняя кнопка отключается от экрана (анимированная), но все остальное остается на экране. На выходе Console две строки распечатываются после выполнения этой строки:

2011-03-14 16: 32: 44,580 TheAppXY [18518: 207] вложенный pop анимация может привести к повреждению панель навигации

2011-03-14 16: 32: 53.507 TheAppXY [18518: 207] Завершение переход в неожиданный государство. Дерево навигации навигации панели навигации может быть поврежден.

Два сообщения об ошибках, на которые я не мог найти ЛЮБОЙ информации. Я использую XCode 4 и iOS SDK 4.3. Может быть, кто-нибудь может помочь мне с этой проблемой.

4b9b3361

Ответ 1

Я столкнулся с аналогичной ситуацией в своем коде, и в сообщении говорилось:

Вложенная анимация push может привести к повреждению панели навигации

Завершение перехода навигации в неожиданном состоянии. Дерево видимости панели навигации > может быть повреждено.

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

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

Следовательно, пока одно представление проходит анимацию, вы не должны запускать анимацию на другом представлении.

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

В моем случае это была проблема с логикой потока, поскольку я не собирался нажимать два контроллера просмотра один за другим. Один из них был вставлен в логику коммутатора, а другой - после его окончания.

Надеюсь, это поможет кому-то.

Ответ 2

Вы можете получить это в любое время, которое вы пытаетесь выполнить перед viewDidAppear. Если вы установите флаг, то просто проверьте этот флаг в viewDidAppear, у вас не будет проблемы.

Ответ 3

Я создал замену для UINavigationController, которая будет останавливать анимацию для вас и полностью исключить эту проблему.

Возьмите его из BufferedNavigationController

Ответ 4

У меня тоже была эта проблема, и вот то, что вызывало мое:

  • В RootViewController я использую несколько объектов UISegmentedControl, чтобы определить, какой из многих видов для загрузки следующий.
  • В этом (суб/2-м) представлении я нажал (с помощью кнопки "Назад" ) обратно в RootViewController.
  • В RootViewController я обрабатывал viewWillAppear для "reset" каждого из моих объектов UISegmentedControl для selectedSegmentIndex -1 (что означает, что сегмент не выглядит "нажатым" ).
  • То, что "reset" вызвало каждый из моих объектов UISegmentedControl, чтобы запустить их связанные (и отдельные) IBActions.
  • Поскольку я не обрабатывал "выбор" из -1, у меня одновременно срабатывало несколько методов, все пытались нажать другое представление.

Мое исправление? Я затянул мои инструкции if... then и выполнил выполнение какого-либо кода в UISegmentedControl IBActions при выбореSegmentIndex == -1.

Я все еще не уверен, почему у меня возникли ошибки "поп-анимации", а не "push", но, по крайней мере, выяснил мою ошибку и исправил ее!

Надеюсь, это поможет кому-то еще!

Ответ 5

Да, к сожалению, яблоко не синхронизировало анимацию UINavigationController. Решение Andrew отлично, но если вы не хотите покрывать всю свою функциональность, есть более простое решение, переопределите эти два метода:

// navigation end event

- ( void )  navigationController    : ( UINavigationController* ) pNavigationController 
            didShowViewController   : ( UIViewController*       ) pController 
            animated                : ( BOOL                    ) pAnimated
{

    if ( [ waitingList count ] > 0 ) [ waitingList removeObjectAtIndex : 0 ];
    if ( [ waitingList count ] > 0 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ];

}


- ( void )  pushViewController  : ( UIViewController* ) pController 
            animated            : ( BOOL ) pAnimated
{

    [ waitingList addObject : pController ];
    if ( [ waitingList count ] == 1 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ];

}

и создайте переменную экземпляра NSMutableArray, называемую waitList, и вы закончите.

Ответ 6

Эта проблема возникает со мной, когда я использую раскадровки. Я допустил ошибку: У меня есть UIButton с действием для выполнения SegueWithIdentifier. Поэтому я связываю push-сегу с Button с другим ViewController, поэтому возникает эта проблема.

Чтобы решить: Свяжите действие кнопки в UIButton и соедините push-сег между двумя ViewControllers.

Ответ 7

Объединяя ответы Милгра и Эндрю, я дал мне то, что работает надежно и является более простой заменой замены UINavigationController.

Это улучшает ответ Милгра, чтобы заставить его работать с толчками и попками, но проще, чем Andrew BufferedNavigationController. (Используя BufferedNavigationController, я иногда получал переходы, которые никогда не будут завершены, и будет показывать только черный экран.)

Вся эта вещь, кажется, не нужна на iOS8, но мне все еще нужно было на iOS7.

@implementation UINavigationControllerWithQueue {
    NSMutableArray *waitingList;
}

-(void) viewDidLoad {
    [super viewDidLoad];
    self.delegate = self; // NOTE: delegate must be self!
    waitingList = [[NSMutableArray alloc] init];
}

# pragma mark - Overrides

-(void) pushViewController: (UIViewController*) controller
                  animated: (BOOL) animated {
    [self queueTransition:^{ [super pushViewController:controller animated:animated]; }];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
    UIViewController *result = [self.viewControllers lastObject];
    [self queueTransition:^{ [super popViewControllerAnimated:animated]; }];
    return result;
}

- (NSArray*)popToRootViewControllerAnimated:(BOOL)animated {
    NSArray* results = [self.viewControllers copy];
    [self queueTransition:^{ [super popToRootViewControllerAnimated:animated]; }];
    return results;
}

# pragma mark - UINavigationControllerDelegate

-(void) navigationController: (UINavigationController*) navigationController
       didShowViewController: (UIViewController*) controller
                    animated: (BOOL) animated {
    [self dequeTransition];
}

# pragma mark - Private Methods

-(void) queueTransition:(void (^)()) transition {
    [waitingList addObject:transition];
    if (waitingList.count == 1) {
        transition();
    }
}

-(void) dequeTransition {
    if (waitingList.count > 0) {
        [waitingList removeObjectAtIndex:0];
    }
    if (waitingList.count > 0) {
        void (^transition)(void) = [waitingList objectAtIndex:0];
        if (transition) {
            transition();
        }
    }
}

@end