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


68

我不断收到以下错误:

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方法有关系吗?

Answers:


118

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


1
无疑,这是对问题的解释
daniherculano

2
如果您在辅助线程上调用pushViewController,也会发生这种情况。
Ben Artin

1
我知道情况会如何。但是,您能否提供一些有关此的文档?它不在UINavigationController文档中
Pietro Rea 2013年

@PietroRea我认为无法在文档中逐字找到这样的主张。但是,医生说pushViewController是“通常用于响应用户选择项目”,即在当前视图可用之后。因此,合乎逻辑的是,期望对这些事件进行重新排序会混淆内部FSM。
SB 2013年

真的,谢谢。您节省了我使用显示菜单的时间,当我将viewcontroller推到viewwillappear上时,一切都是假的。真的谢谢你:)
Erhan Demirci 2014年

92

两次成功触发相同的SEGUE两次, 一次是在代码中,一次是从界面生成器中,但是在同一时间...

我遇到的错误与你们其他人一样。唯一的问题是我不小心开了两次相同的射击。一次来自界面构建器,一次来自我的代码。

我有一个UITableView。选择一个单元后,将触发界面生成器中的segue。这是我的问题,我将segue设置为直接单击界面构建器中的CELL ITSELf,然后在我的代码中使用了didSelectRowAtIndexPath,该代码将触发相同的segue。

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

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

因此,如果您由于与我相同的原因而遇到此问题,也就是说,您两次调用相同的segue,则可以通过取消直接将CELL直接连接到您的segue并使segue连接起源于此链接来解决此问题。 IB中表格层次结构的顶部,而不是嵌套在单元格内部。将序列从您的View Controller本身连接到序列。如果已正确完成此操作,则在选择segue时,它应突出显示它来自的整个视图,而不仅仅是单元格。

现在,Apple文档因此在performSegueWithIdentifier:sender:引用下声明:

应用通常不需要直接触发搜寻。相反,您可以在与视图控制器关联的Interface Builder中配置一个对象(例如,嵌入在其视图层次结构中的控件)来触发segue。但是,您可以调用此方法以编程方式触发segue,也许是响应故事板资源文件中无法指定的某些动作。例如,您可以从用于处理震动或加速度计事件的自定义动作处理程序中调用它。

就我而言,我有一个用于UITableView的搜索按钮,并且必须确定是否在存在搜索结果表或存在普通表视图时调用segue。所以我需要直接触发搜寻。

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

现在,不再需要双关!没有更多的错误。

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


1
我的问题也是由两次触发按钮引起的
lomec

11
主席先生,是救生员。
geekchic

1
我已经UICellView在IB中设置了一个序列,然后实现了代码来创建新的VC self.storyboard,并将我的数据传递到该VC,然后继续进行[self.navigationController pushViewController:vc animated:YES];。我的解决方案是删除IB中的segue。
2014年

我没有使用情节提要。我正在使用pushviewcontroller。如何预防这个问题?
Gajendra K Chauhan 2014年

13

我遇到了与您刚才相同的问题/错误消息,正在寻找解决方案并最终到达此线程,但是,对我来说,我发现该解决方案实际上只有一个动画:执行嵌套推送时(是放动画:仅在最后一次推送时为“是”),希望这对您有所帮助

干杯。


您的评论使我能够解决这个难题-请参阅下面对已接受答案的评论,它可能对将来也有帮助。
查尔斯·兰德尔

我没有收到错误,但是从第三个视图弹出后,我的第一个视图的导航栏显示了中间视图的导航栏。不从顶部动画流行音乐可以解决问题。
条例草案

谢谢,当您提到它时,它就变得非常有意义。我先用animation:YES来推动初始控制器,然后再用animated:NO来推动我的剩余控制器,以使用户到达正确的位置。
Kalle 2012年

9

我知道了。显然,如果您从UITableViewDelegate的-didSelectRowAtIndexPath方法之外调用-pushViewController,它将无法正常工作。将调用移至该函数即可。奇怪的。


20
这解决了该问题,因为在视图完成动画处理之前,不能调用didSelectRowAtIndexPath。如果您只是简单地确保在viewDidAppear:或更高版本中调用pushViewController,iOS将不会抱怨嵌套的pushViewController调用。
查尔斯·兰德尔

我真的不明白“显然,如果您从UITableViewDelegate的-didSelectRowAtIndexPath方法外部调用-pushViewController,它将无法正常工作。”。它在我的项目中有效。
汉森·芳

8

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


3
我也有类似的问题。就我而言,我有情节提要剧集和程序化剧集(performSegueWithIdentifier)的混合体。当我意外地同时执行两个操作时,出现了此错误。
2012年

2
这也是我的问题。我有“推”到下一个控制器的静态表单元格。我在didSelectRowAtIndexPath中也有一个performSegueWithIdentifier。都被呼叫导致此消息。
ekawas 2012年

我的问题几乎正是此答案中所述的问题,仅在IB中,我对同一按钮有两种相同的操作。我确信这是因为我在IB中使用了复制和粘贴。小心。
Alyoshak 2013年

4

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

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

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


1
我说我在viewDidLoad或loadView上使用init的唯一原因是因为Apple的示例应用程序不使用init方法来设置视图,所以我认为这可能是其中的一部分。同样,即使我注释掉了init方法中的所有代码后,仍然遇到此问题。如果是这种情况,为什么对于SingleEventViewController也不会发生呢?
joshholat 2011年

您无需使用init来设置UI /视图项-这不是平常的地方。请仔细阅读UIViewController文档。可以从笔尖加载视图。或者,您可以在loadView中以编程方式进行操作。或者,您可以通过笔尖设置基本视图,然后以编程方式在viewDidLoad中添加更多项。但是您不应该在init中做这种事情。
occulus 2011年

我以编程方式进行。因此,我应该分配内存并设置loadView中的所有属性,然后将这些东西实际添加到init的视图中吗?因为如果我尝试这样做[self.view addSubview:myTableView]; 在loadView方法中,它崩溃了。
joshholat 2011年

是的,如果仅在ViewDidLoad方法中执行Perform Segue,则会出现上述错误,不仅在下一个ViewController中,那里的contentViews损坏了,而且它们显示的是较早的From View Controller内容。所以我要做的是,我从ViewDid Load中删除了performSegue方法调用,并将其放在Button操作上,并解决了问题。而且我已经尝试并浪费了ViewDid Load方法中的该方法调用,只是出于测试目的!因为我需要在加载View之后立即执行此操作,因此我将其与ViewDidLoad分开了。
Randika Vishman

2

嗯,我遇到了这个问题,我是整个iOS开发人员的新手。但是,在界面构建器中查看了我的连接检查器(带有文件的所有者)后,我看到当我复制一个按钮时,它既分配了先前的button方法又创建了新方法。我猜这就是我的问题嵌套方面的出处,因为它执行两种不同的方法,这两种方法都会将视图推到Nav Controller上。我知道这个问题已经得到解决,但我想我会提出来,以防万一其他人有像我这样的愚蠢错误。


1

这已经得到了回答,但是我认为这可能对其他人有所帮助,因为我遇到了相同的错误,但是没有使用表视图。我终于找到了问题所在。

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


1

遇到同样的问题。就我而言,我错过了switch语句中的中断,因此同时触发了两个segue。为我轻松解决。


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堆栈。



0

1)也许您可以先尝试将必要的变量作为属性传递,然后再按 UIViewController而不要使用带有参数的init方法。无论如何,您很有可能需要超出init方法的这些参数。

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

2)就像您提到的那样viewDidLoad-此方法用于视图加载后的初始化。如果像看起来那样用代码创建UIViewController,则应该使用它loadView来设置子视图。


initWithCoordinates方法还没有参数。我计划添加它们,但随后首先遇到此问题,并在继续进行之前尝试对其进行调试。但是,为什么SingleEventViewController也不是这种情况呢?它在必须设置的init处接受参数。谢谢,我将尝试使用loadView。
joshholat 2011年

0

这是因为我的缘故 UIControlEvents

    [button addTarget:self action:@selector(callSecondView) forControlEvents:UIControlEventAllTouchEvents];

我必须将更UIControlEventAllTouchEvents改为UIControlEventTouchUpInside,但是如果由于UIButton调用而出现问题,则希望按钮能够正常工作。


0

我的解决方案是

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


0

不知道别人的。我认为大多数使用StoryBoard的人都面临这样的问题。我正在使用XIB。

就我的问题而言,当我使用推移到另一个视图时,我也在使用

 [self.navigationController popViewControllerAnimated:YES];

在当前视图的ViewWillDisappear中同时显示。只需将其删除,即可正常工作。

由于需求和流程的原因,我正在使用POP。层次结构是1-> 2-> 3

我在视图2上,并想移至视图3。在那种情况下,我遇到了此错误。


0

以我为例,我既从情节提要中设置了推键,又以编程方式设置了推键。希望能对任何人有帮助


0

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

文档清楚地指出,调用super是在重写viewDidLoad时应该执行的操作,而我是很难学到的。

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


0

我知道已经回答了,但是可以帮助其他人。

我遇到了同样的问题,但这是由于我在信息按钮上使用了错误事件而引起的。我使用的是“ UIControlEventAllTouchEvents”,这将同一视图两次推入导航控制器。正确的事件是“ UIControlEventTouchUpInside”。我是iOS新手。


-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 Demo [2840:60b]完成导航状态的意外转变。导航栏子视图树可能已损坏。

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


-1

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

我确实在TabBarController中设置了几个NavigationController,并在情节提要中的Identifiy Properties中设置了selectedIndex。将活动的Tab键移至Code后,错误消失了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.