2011-03-14 87 views
49

我一直在寻找一个解决方案的互联网。我找不到任何东西。因此: 我使用的是UINavigationController。我推着两个UIViewControllers。在第二个推视图控制器我执行此代码:iOS:popViewController意外行为

- (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。也许任何人都可以帮助我解决这个问题。

+1

我想我自己想通了。我认为这是因为我试图过早地弹出视图控制器。如果反向地理编码器提供了一个地址(该地址在ViewDidLoad中启动)并且失败,那么该视图还没有出现,所以动画弹出不太明显。我现在在ViewDidAppear中实现了Reverse Geocoder的开始,并且一切似乎都正常。新手错误或多或少。但我不知道有没有关于它的信息 – Christoph 2011-03-14 16:18:22

+0

最近,我遇到了同样的问题。原因是: - 我试图错误地弹出视图控制器两次。你可以通过在push和pop上设置断点来检查这个崩溃。视图控制器 – 2014-07-31 09:07:47

回答

28

您可以在任何时候尝试在viewDidAppear之前弹出。如果你设置了一个标志,那么只需在viewDidAppear中检查该标志,你就不会有问题。

+0

这似乎是最安全的方法 – Dmytro 2016-03-24 22:09:05

50

我遇到类似的情况在我的代码来了,留言说:可能导致损坏的导航栏

整理了意外状态导航过渡

嵌套推动画。导航栏子视图树>可能会损坏。

我对这个问题的发现是,我一个接一个地连续推动2个视图控制器,并且都是动画的。

在你的情况,似乎你可能会弹出多个视图控制器与动画一个接一个。

因此,当一个视图正在进行动画时,您不应该在另一个视图上启动动画。

我还发现,如果我在一个视图上禁用了动画,错误消息就消失了。

在我的情况下,这是一个流逻辑的问题,因为我不打算一个接一个地推动2个视图控制器。一个人在开关柜逻辑中被推入,另一个在结束后被推入。

希望这可以帮助别人。

+10

他们在这里输入的关键字是:“...并且都是动画。”谢谢! – 2011-08-05 17:58:14

+0

您是否有任何建议来处理您希望这样做的情况?例如,当我将视图控制器推入堆栈时,我会看到很多,然后显示一个UIAlertView。我仍然想要展示他们两个,我只是希望View被推入堆栈,然后显示alert视图而不必实现一堆委托方法。 – dsingleton 2012-06-08 20:48:34

+3

感谢当我更改为'Animated:YES'到'Animated:NO'并且在'viewDidAppear'上调用我的pop方法时,感谢解决了问题 – 2012-11-02 15:39:47

3

我有这个问题,也和这里是什么导致我的:

  1. 在RootViewController的,我用几个UISegmentedControl对象以确定其中许多意见旁加载。
  2. 在那个(sub/2nd)视图中,我弹出(通过使用“返回”按钮)回到RootViewController。
  3. 在RootViewController中,我正在处理viewWillAppear以将每个UISegmentedControl对象“重置”为-1的selectedSegmentIndex(意味着没有看起来像“按下”的段)。
  4. “重置”触发我的每个UISegmentedControl对象触发其关联(和单独)的IBActions。
  5. 因为我没有处理-1的“选择”,所以我有多个方法在同一时间触发,所有尝试推入不同的视图。

我的修复?我收紧了我的if ... then语句,并在selectedSegmentIndex == -1时保留在我的UISegmentedControl IBActions中执行任何代码。

我仍然不确定为什么我会弹出动画错误,而不是“推”错误,但至少弄清了我的错误并修复了错误!

希望这可以帮助别人!

12

我已经为UINavigationController创建了一个替代插件,它将为您排队动画并完全避免此问题。

抓住它从BufferedNavigationController

+0

嘿安德鲁,你还支持上面的课吗?由于某种原因,它不适合我,因为你可以在这里看到:http://stackoverflow.com/questions/16634337/right-to-left-push-animation-results-in-corrupted-navigation-bar – Segev 2013-05-19 17:10:04

+0

另请参见我的UINavigationControllerWithQueue回答下面,替代 – MarkWPiper 2015-06-20 07:34:40

0

是啊,可惜的是苹果没有同步的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 ]; 

} 

并创建一个名为waitingList一个NSMutableArray实例变量,和你做。

+0

我接受了这个想法,并将其推广到以下答案中的popViewController *,UINavigationControllerWithQueue – MarkWPiper 2015-06-20 07:37:08

0

当我使用故事板时,这个问题发生在我身上。我犯了一个错误: 我有一个UIButton执行SegueWithIdentifier的动作。所以我把push segue与Button和另一个ViewController联系起来,所以发生这个问题。

解决方法: 链接UIButton中的按钮动作并链接两个ViewController之间的push segue。

0

结合MilGra和Andrew的回答给了我一些可靠工作的东西,并且是一个更简单的插入式UINavigationController替换。

这改进了MilGra的答案,使其能够处理推送和弹出,但比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 
+0

在模拟器中工作得很好,但在设备上不可靠 - 所以最终不是推荐的方法。 – MarkWPiper 2015-07-13 18:04:21