【问题标题】:iPhone UINavigation Issue - nested push animation can result in corrupted navigation bariPhone 导航问题 - 嵌套推送动画可能导致导航栏损坏
【发布时间】:2011-07-28 09:15:55
【问题描述】:

我不断收到以下错误:

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 方法是否重要?

【问题讨论】:

    标签: iphone ios4 uinavigationcontroller navigationcontroller


    【解决方案1】:

    viewDidAppear 之前调用pushViewController 是不安全的。

    【讨论】:

    • 这肯定是问题的解释
    • 如果你在辅助线程上调用 pushViewController 也会发生。
    • 我知道会是这样。但是,您能否提供一些有关此问题的文档?它不在 UINavigationController 文档中
    • @PietroRea 我不认为可以在文档中逐字找到这样的声明。但是,文档说 pushViewController “通常用于响应用户选择项目”,即在当前视图可用之后。因此,重新排序这些事件可能会混淆内部 FSM 是合乎逻辑的。
    • 真的谢谢你。你节省了我使用显示菜单的时间,当我在 viewwillappear 上按下 viewcontroller 时,一切都是错误的。真的谢谢你:)
    【解决方案2】:

    意外触发同一个 SEGUE 两次 一次在代码中,一次来自界面生成器,但两者同时...

    我遇到了和你们其他人一样的错误。只有我的问题是我不小心两次触发了相同的segue。一次来自界面生成器,一次来自我的代码。

    我有一个 UITableView。当一个单元格被选中时,界面生成器中的一个 segue 会触发。这是我的问题,我将segue设置为直接触发单击CELL ITSELf,在界面构建器内,然后在我的代码中,我在didSelectRowAtIndexPath下,代码会触发相同的segue......就像这样......

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

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

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

    现在 Apple 的文档在 performSegueWithIdentifier:sender:reference 下如此声明:

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

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

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

    现在,不要再重复了!并且没有更多错误。

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

    【讨论】:

    • 我的问题也是由两次触发按钮引起的
    • 先生,您是救命稻草。
    • 我在 IB 中为 UICellView 设置了一个 segue,然后我实现了代码以通过 self.storyboard 创建一个新的 VC,并将我的数据传递给该 VC,然后通过 [self.navigationController pushViewController:vc animated:YES]; 推送。我的解决方案是删除 IB 中的 segue。
    • 我没有使用故事板。我正在使用 pushviewcontroller。如何预防这个问题?
    【解决方案3】:

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

    干杯。

    【讨论】:

    • 您的评论让我解决了这个难题——请参阅我对下面已接受答案的评论,它也可能在将来对您有所帮助。
    • 我没有收到错误,但我的第一个视图的导航栏在从第三个视图弹出后显示了中间视图的导航栏。不从顶部动画弹出解决了这个问题。
    • 谢谢,当你提到它时,这很有意义。我用 animated:YES 推送了初始控制器,然后用 animated:NO 推送了其余的控制器以将用户带到正确的位置。
    【解决方案4】:

    我想通了。显然,如果您从 UITableViewDelegate 的 -didSelectRowAtIndexPath 方法之外调用 -pushViewController,它就不起作用。将调用移到该函数中有效。很奇怪。

    【讨论】:

    • 这解决了这个问题,因为在视图完成动画之前无法调用 didSelectRowAtIndexPath。如果您只是确保在 viewDidAppear: 或更高版本中调用 pushViewController,iOS 将不会抱怨嵌套的 pushViewController 调用。
    • 我不太明白“显然,如果你从 UITableViewDelegate 的 -didSelectRowAtIndexPath 方法之外调用 -pushViewController,它就不起作用。”它在我的项目中有效。
    【解决方案5】:

    我遇到了同样的问题,它是由于笔尖中的一个按钮连接到两个不同的操作而导致的。它尝试加载两个视图控制器,从而破坏了堆栈。

    【讨论】:

    • 我也有类似的问题。就我而言,我混合了故事板转场和程序转场(performSegueWithIdentifier)。当我不小心同时做了这两个操作时,我得到了这个错误。
    • 这也是我的问题。我有“推”到下一个控制器的静态表格单元格。我在 didSelectRowAtIndexPath 中也有一个 performSegueWithIdentifier。两者都被调用导致此消息。
    • 我的问题几乎与此答案中描述的完全一样,只是在 IB 中,我不知何故对同一个按钮有两个相同的操作。我确信这是因为我在 IB 中使用了复制和粘贴。小心。
    【解决方案6】:

    你说你使用 init 方法而不是 viewDidLoad 方法是什么意思?

    如果你在旧的推送没有被执行的机会之前推送一个新的视图控制器,你会得到这种错误。因此,将某些代码放入 init 并过早执行操作肯定会导致您报告错误。

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

    【讨论】:

    • 我之所以说我使用 init 而不是 viewDidLoad 或 loadView 的唯一原因是因为 Apple 的示例应用程序不使用 init 方法来设置视图,所以我认为这可能是其中的一部分。另外,即使我注释掉了 init 方法中的所有代码,我仍然会遇到这个问题。但是,如果是这样的话,为什么 SingleEventViewController 不会发生这种情况呢?
    • 您不使用 init 来设置您的 UI/视图项目——这不是通常的地方。仔细查看 UIViewController 文档。可以从 nib 加载视图。或者您可以在 loadView 中以编程方式执行此操作。或者,您可以通过 nib 设置基本视图,然后以编程方式在 viewDidLoad 中添加更多项目。但你不应该在 init 中做那种事情。
    • 我以编程方式进行。那么我是否应该分配内存并在 loadView 中设置所有属性,然后将这些内容实际添加到 init 中的视图中?因为如果我尝试这样做 [self.view addSubview:myTableView];在 loadView 方法中,它崩溃了。
    • 地狱是的,如果我们只在 ViewDidLoad 方法中执行执行 Segue,它会给出上述错误,不仅在下一个 ViewControllers 中,contentViews 已损坏,它们会显示相同的旧从视图控制器内容。所以我所做的是,我从 ViewDid Load 中删除了 performSegue 方法调用,并将其放到 Button 操作上,问题就解决了。我曾尝试在 ViewDid Load 方法中浪费了该方法调用,只是为了测试目的!因为我需要在 View 加载后立即执行此操作。所以我将它与 ViewDidLoad 分开。
    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        【解决方案9】:

        遇到了同样的问题。就我而言,我错过了 switch 语句中的中断,因此同时触发了两个 segue。对我来说很容易解决。

        【讨论】:

          【解决方案10】:

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

          这是通过从 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 堆栈。

          【讨论】:

            【解决方案11】:

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

            【讨论】:

              【解决方案12】:

              1) 也许您可以在推送UIViewController 之前尝试将必要的变量作为属性传递,而不是使用带参数的init 方法。无论如何,您很可能在 init 方法之外还需要这些参数。

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

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

              【讨论】:

              • initWithCoordinates 方法还没有参数。我计划添加它们,但后来首先遇到了这个问题,并在继续之前尝试调试它时被抓住了。但是,为什么 SingleEventViewController 也不是这样呢?它在它必须设置的 init 中获取参数。谢谢,我会尝试使用 loadView。
              【解决方案13】:

              这对我来说是因为我的UIControlEvents

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

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

              【讨论】:

                【解决方案14】:

                我的解决方案是

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

                【讨论】:

                  【解决方案15】:

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

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

                   [self.navigationController popViewControllerAnimated:YES];
                  

                  在当前View的ViewWillDisappear的同时。只需将其删除即可正常工作。

                  由于需求和流程,我使用了 POP。 层次结构是 1 -> 2 ->3

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

                  【讨论】:

                    【解决方案16】:

                    就我而言,我既是从情节提要中设置推送转场,也是以编程方式设置。希望这会帮助任何人

                    【讨论】:

                      【解决方案17】:

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

                      调用 super 是文档明确指出您在覆盖 viewDidLoad 时应该做的事情,我是通过艰难的方式学会了这一点。

                      也许这对其他人也有帮助!

                      【讨论】:

                        【解决方案18】:

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

                        我遇到了同样的问题,但这是因为我为信息按钮使用了错误事件。 我正在使用“UIControlEventAllTouchEvents”,这会在导航控制器中生成两个相同视图的推送。正确的事件是“UIControlEventTouchUpInside”。我是 iOS 新手。

                        【讨论】:

                          【解决方案19】:

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

                          如果您使用动画(动画:YES)推送(或弹出)视图控制器,它不会立即完成,如果您在动画完成之前再次推送或弹出,则会发生不好的事情。

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

                          - (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 的子类,就可以了。

                          【讨论】:

                            【解决方案20】:

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

                            我确实在 TabBarController 中设置了几个 NavigationController 并设置了 情节提要中的 selectedIndex 标识属性。将活动选项卡移动到代码后错误消失了。

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-09-19
                              • 2013-11-22
                              相关资源
                              最近更新 更多