iPhone导航问题 - 嵌套推送动画可能导致导航栏损坏

时间:2011-04-02 20:00:06

标签: iphone ios4 uinavigationcontroller navigationcontroller

我一直收到以下错误:

2011-04-02 14:55:23.350 AppName[42430:207] nested push animation can result in corrupted navigation bar
2011-04-02 14:55:23.352 AppName[42430:207] nested push animation can result in corrupted navigation bar
2011-04-02 14:55:23.729 AppName[42430:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2011-04-02 14:55:23.729 AppName[42430:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

这是我正在做的事情。从视图控制器,我按下某个按钮时调用以下内容:

EventsViewController *viewController = [[EventsViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
navController.navigationBar.tintColor = [UIColor blackColor];
[self presentModalViewController:navController animated:YES];
[viewController release];
[navController release];

然后,如果在EventsController中按下某个按钮,我会调用:

SingleEventViewController *viewController = [[SingleEventViewController alloc] initWithEvent:[currentEvents objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];

然后,如果在SingleEventViewController中按下某个按钮,我会调用:

EventMapView* viewController = [[EventMapView alloc] initWithCoordinates];
[[self navigationController] pushViewController:viewController animated:YES];
[viewController release];

所以,很明显,有嵌套的推动动画,但这不是正确的方法吗?我检查了Apple的DrillDownSave代码,看起来他们是这样做的。我使用init方法而不是viewDidLoad方法是否重要?

20 个答案:

答案 0 :(得分:118)

pushViewController之前致电viewDidAppear是不安全的。

答案 1 :(得分:93)

事故触发同样的情况两次 一旦进入代码,一次来自界面构建器,但两者同时......

我和其他人一样得到了同样的错误。只有我的问题是我偶然发射了两次相同的赛格。一次来自界面构建器,一次来自我的代码。

我有一个UITableView。选择单元格后,界面构建器中的segue将触发。继承了我的问题,我将segue设置为直接点击CELL ITSELf,在界面构建器中,然后在我的代码中,我在didSelectRowAtIndexPath下,代码将触发相同的segue ...就像这样... < / p>

[self performSegueWithIdentifier:@"MySegue" sender:tableView];

这意味着当选择了一行来调用didSelectRowAtIndexPath时,它会使用上面的代码行触发segue。然后接口构建器也会触发segue,因为它直接连接到接口构建器中的单元对象。阻止界面构建器直接触发segue。你必须从视图控制器的顶部连接segue,而不是嵌套在从单元本身出来的内部。

因此,如果您出于与我相同的原因遇到此问题,也就是说,您正在调用两次相同的segue,您可以通过将连接从CELL直接链接到您的segue并使用segue连接来解决此问题起源于IB中表层次结构的顶部,而不是嵌套在单元格内部。将视图控制器本身的segue连接到segue。如果你做得正确,当你选择segue时,它应该突出显示它来自的整个视图,而不仅仅是单元格。

现在,Apples文档在performSegueWithIdentifier:sender:reference:

下声明

应用通常不需要直接触发segue。而是在Interface Builder中配置与视图控制器关联的对象(例如嵌入在其视图层次结构中的控件)以触发segue。但是,您可以调用此方法以编程方式触发segue,可能是为了响应无法在storyboard资源文件中指定的某些操作。例如,您可以从用于处理摇动或加速计事件的自定义操作处理程序中调用它。

在我的情况下,我有一个UITableView的搜索按钮,以及当搜索结果表存在时是否调用segue,或者是否存在普通表视图时,必须确定。所以我需要直接触发segue。

因此,从界面构建器中删除嵌入式控件,只需将其粘贴在视图控制器本身上,然后在代码中触发segue!

现在,不再是双重的!没有更多的错误。

希望有所帮助,花了我几个小时来解决这个问题。

答案 2 :(得分:12)

我遇到了与你刚才做的相同的问题/错误信息,正在寻找解决方案并最终在这个线程,但是,对我来说,我发现解决方案实际上只有一个动画:是的,当做嵌套推(我把动画:YES仅用于最后推送),希望这有帮助

欢呼声。

答案 3 :(得分:10)

我已经弄清楚了。显然,如果从UITableViewDelegate的-didSelectRowAtIndexPath方法之外调用-pushViewController,它就不起作用。将呼叫转移到该功能有效。怪异。

答案 4 :(得分:8)

我遇到了同样的问题,因为笔尖中的按钮连接到两个不同的动作。它尝试加载两个视图控制器,从而破坏堆栈。

答案 5 :(得分:4)

当您说使用init方法而不是viewDidLoad方法时,您的意思是什么?

如果您在旧推送操作错误之前推送新的视图控制器,则会出现此类错误。因此,将某些代码放入init并过早地执行操作肯定会让您报告错误。

在视图控制器上运行init时,视图尚未加载!

答案 6 :(得分:2)

嗯,我有这个问题,而且我是整个iOS开发场景的新手。但是在界面构建器中查看我的连接检查器(带文件所有者)之后,我看到,因为我复制了一个按钮,它分配了前面的按钮方法以及我创建的新方法。我想这就是我的问题的嵌套方面来自哪里,因为它正在执行两种不同的方法,这两种方法都将视图推送到导航控制器上。我知道这已经得到了回答,但我想我会把它放在一起以防万一其他人像我一样犯了一个愚蠢的错误。

答案 7 :(得分:1)

这已经得到了解答,但我认为这可能对其他人有帮助,因为我得到了相同的错误,但没有使用表格视图。我终于弄明白了这个问题。

我有一个现有按钮,其IBAction调用了pushViewController。我通过复制现有按钮创建了一个新按钮。新按钮还有一个调用pushViewController的动作。当点击新按钮(内部触摸)并按下视图控制器时,我收到此错误。我删除了新按钮,从头开始创建它,将其绑定到现有的插座和操作,错误就消失了。

答案 8 :(得分:1)

遇到同样的问题。在我的情况下,我错过了switch语句中的中断,因此同时触发了两个segues。对我来说很容易解决。

答案 9 :(得分:1)

我的问题与键盘处于活动状态有关。

这是通过从textField的委托方法推送ViewController而引起的:

-(void)textFieldDidBeginEditing:(UITextField *)textField{

        FilterLocationViewController *destViewController = (FilterLocationViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"FilterLocationViewController"];

        [self.navigationController pushViewController:destViewController animated:YES];

}

将代码更改为:

-(void)textFieldDidBeginEditing:(UITextField *)textField{

        [_textFieldLocation resignFirstResponder]; //adding this line

        FilterLocationViewController *destViewController = (FilterLocationViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"FilterLocationViewController"];

        [self.navigationController pushViewController:destViewController animated:YES];

}

(添加行[textField resignFirstResponder];)问题消失了。

基本上,教训是如果键盘不在,你不应该修改navigationController堆栈。

答案 10 :(得分:1)

最近,我遇到了同样的问题。原因是: - 我试图错误地两次弹出视图控制器。您可以通过在推送和弹出视图控制器上设置断点来检查此崩溃

答案 11 :(得分:0)

1)也许您可以尝试在推送UIViewController之前将必要的变量作为属性传递,而不是将init方法与参数一起使用。最有可能的是,除了init方法之外,你还需要这些参数。

此外,在您的initWithCoordinates:方法中,您缺少参数。可能你的自定义init方法是问题的一部分。

2)仅仅因为你提到viewDidLoad - 这个方法是在加载视图后进行初始化。如果您在代码中创建UIViewController,就像您一样,您应该使用loadView来设置子视图。

答案 12 :(得分:0)

我知道这已得到回答,但它可以帮助其他人。

我遇到了同样的问题,但这是因为我在信息按钮上使用了错误的事件。  我正在使用&#34; UIControlEventAllTouchEvents&#34;这产生了两次将同一视图推入导航控制器。正确的事件是&#34; UIControlEventTouchUpInside&#34;。我是iOS新手。

答案 13 :(得分:0)

我也有这个错误消息,导航栏和导航控制器转换很奇怪。我的设置是嵌入在标签栏控制器中的一堆导航控制器。问题是我没有在super.viewDidLoad()的标签栏控制器实现中调用viewDidLoad

调用super是文档明确指出你应该在覆盖viewDidLoad时做的事情,而且我很难学到这一点。

也许这也可以帮助其他人!

答案 14 :(得分:0)

在我的情况下,我正在以故事板和编程方式设置push segue。希望能帮助任何人

答案 15 :(得分:0)

不知道其他的。我想大多数使用StoryBoard的人都面临着这样的问题。我正在使用XIB。

在我的情况下问题是,当我使用推送移动到另一个视图时, 我也在使用

 [self.navigationController popViewControllerAnimated:YES];

同时在当前View的ViewWillDisappear中。只需删除它就可以了。

我正在使用POP,因为需求和Flow。 层次结构是1 - > 2 - &gt; 3

我在视图2上,想要移动到视图3.在这种情况下,我遇到了这个错误。

答案 16 :(得分:0)

由于我的UIControlEvents

,这种情况正在发生
    [button addTarget:self action:@selector(callSecondView) forControlEvents:UIControlEventAllTouchEvents];

我必须将UIControlEventAllTouchEvents更改为UIControlEventTouchUpInside,或者如果您因为UIButton调用而遇到问题,则需要按钮才能正常工作。

答案 17 :(得分:0)

我的解决方案是

  

[self performSelector:@selector(moveTo)withObject:nil   afterDelay:0.5];

答案 18 :(得分:-1)

这解决了这个问题: https://github.com/nexuspod/SafeTransition

如果您使用动画(动画:是)推动(或弹出)视图控制器,它不会立即完成,如果您在动画完成之前执行另一次推送或弹出,则会发生不良事件。

要重现此错误,请尝试同时推送或弹出两个视图控制器。例如:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIViewController *vc = [[UIViewController alloc] init];
    [self.navigationController pushViewController:vc animated:YES];
}

您将收到此错误:

  

2014-07-03 11:54:25.051 Demo [2840:60b]嵌套推送动画可以   导致导航栏损坏2014-07-03 11:54:25.406   演示[2840:60b]完成意外的导航过渡   州。导航栏子视图树可能已损坏。

只需将代码文件添加到项目中,并将导航控制器作为APBaseNavigationController的子类,您就可以了。

答案 19 :(得分:-1)

只是为了完成列表,这是另一个可能导致嵌套推送动画可能导致导航栏损坏的原因&#34;:

我在TabBarController中设置了几个NavigationController并进行了设置 故事板中的selectedIndex标识属性。将活动标签移动到代码后,错误消失了。