iOS: popViewController неожиданное поведение - PullRequest
49 голосов
/ 14 марта 2011

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

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

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

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

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

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

Ответы [ 7 ]

50 голосов
/ 19 мая 2011

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

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

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

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

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

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

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

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

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

28 голосов
/ 07 мая 2011

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

12 голосов
/ 20 декабря 2011

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

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

3 голосов
/ 14 июня 2011

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

  1. В RootViewController я использую несколько объектов UISegmentedControl, чтобы определить, какое из многих представлений загрузить следующим.
  2. В этом (sub / 2nd) виде я снова (используя кнопку «Назад») возвращался к RootViewController.
  3. В RootViewController я обрабатывал viewWillAppear для «сброса» каждого из моих объектов UISegmentedControl в selectedSegmentIndex со значением -1 (что означает, что ни один сегмент не выглядит «нажатым»).
  4. Это «сброс» вызвал каждый из моих объектов UISegmentedControl для запуска их связанных (и отдельных) IBActions.
  5. Поскольку я не обрабатывал «выделение» из -1, у меня было несколько методов, запущенных одновременно, и все пытались выдвинуть другое представление.

Мое исправление? Я ужесточил свои операторы if ... then и поручился выполнить любой код в моих IBActions UISegmentedControl, когда selectedSegmentIndex == -1.

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

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

0 голосов
/ 20 июня 2015

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

Это улучшает ответ MilGra, чтобы он работал с толчками и щелчками, но проще, чем Andrew's 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
0 голосов
/ 14 августа 2013

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

Решение: связать действие кнопки в UIButton и связать push-segue между двумя ViewController.

0 голосов
/ 02 марта 2012

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

// 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, и все готово.

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