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

发布于 2024-10-28 16:33:43 字数 1683 浏览 1 评论 0原文

我不断收到以下错误:

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

I keep getting the following errors:

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.

Here is what I am doing. From a view controller, I call the following when a certain button is pushed:

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];

Then, if a certain button is pushed in EventsController, I call:

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

Then, if a certain button is pushed in SingleEventViewController, I call:

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

So yea, it's obvious that there's nested push animations, but isn't this the right way to go about it? I checked out Apple's DrillDownSave code and this appears to be how they're doing it. Does it matter that I use init methods instead of viewDidLoad methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

花伊自在美 2024-11-04 16:33:44

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

我确实在 TabBarController 中设置了几个 NavigationController 并设置
故事板标识属性中的 selectedIndex。将活动选项卡移至代码后,错误消失了。

Just to complete the list, here is another reason which can cause "nested push animation can result in corrupted navigation bar":

I did setup several NavigationController within a TabBarController and set
the selectedIndex within the storyboard Identifiy Properties. After moving active Tab to Code error disappeared.

望她远 2024-11-04 16:33:43

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

Calling pushViewController before viewDidAppear is unsafe.

夕嗳→ 2024-11-04 16:33:43

意外触发同一个 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: 参考下指出:

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

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

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

现在,不再需要双重转场了!并且不再有错误。

ACCIDENTLY TRIGGERING THE SAME SEGUE TWICE
Once in code, and once from interface builder, but both at the same time...

I was getting the same error as the rest of you. Only my problem was I was accidentally firing the same segue, twice. Once from interface builder, and once from within my code.

I have a UITableView. When a cell is selected, a segue in interface builder fires. Heres my problem, I had the segue set up to be directly fired off clicking the CELL ITSELf, inside interface builder, then in my code, I had under didSelectRowAtIndexPath, code that would fire that same segue... like so...

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

That means when didSelectRowAtIndexPath gets called because a row was selected, it fires the segue with the above line of code. Then interface builder, also triggers the segue, because its connected directly to the cell object in interface builder. To stop interface builder from directly firing the segue. You have to connect the segue from the top of the view controller, not nested down inside coming off of the cell itself.

So if you are having this problem for the same reason as me, that is, you are calling the same segue twice, you can fix this by unlinking the connection from the CELL DIRECTLY, to your segue, and having the segue connection originate at the top of the table hierarchy in IB, rather than nested inside the cell. Connect the segue from you View Controller itself, to the segue. If you have done this correct, when you select the segue, it should highlight the ENTIRE view it is coming from, not just the cell.

Now Apples documentation states thus under the performSegueWithIdentifier:sender: reference:

Apps normally do not need to trigger segues directly. Instead, you configure an object in Interface Builder associated with the view controller, such as a control embedded in its view hierarchy, to trigger the segue. However, you can call this method to trigger a segue programmatically, perhaps in response to some action that cannot be specified in the storyboard resource file. For example, you might call it from a custom action handler used to process shake or accelerometer events.

In my case, I have a search button for my UITableView, and whether the segue is called when the search results table is present, or the normal table view is present, had to be determined. So I needed to trigger the segue directly.

So remove the embedded control from interface builder, and just stick it on the view controller itself, then trigger the segue in your code!

Now, no more double segues! And no more errors.

像你 2024-11-04 16:33:43

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

干杯。

I had the same problem / error message as you did just now, was looking for a solution and ended up at this thread, however, for me I found that the solution is actually having only one animated:YES when doing a nested push (I put animated:YES only for the final push), hope this helps

cheers.

爱,才寂寞 2024-11-04 16:33:43

我已经弄清楚了。显然,如果您从 UITableViewDelegate 的 -didSelectRowAtIndexPath 方法外部调用 -pushViewController,它将不起作用。将调用移动到该函数中是有效的。诡异的。

I've figured it out. Apparently if you call -pushViewController from outside of the -didSelectRowAtIndexPath method of a UITableViewDelegate, it doesn't work. Moving the call into that function worked. Weird.

虐人心 2024-11-04 16:33:43

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

I happened upon this same problem that resulted from a button in a nib being connected to two different actions. It tried loading both view controllers, thereby corrupting the stack.

ㄖ落Θ余辉 2024-11-04 16:33:43

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

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

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

What do you mean when you say you use init methods instead of viewDidLoad methods?

If you're pushing a new view controller before the old push has bad a chance to be actioned, you will get this sort of error. So putting certain code into init and doing things prematurely could certainly get you the error being reported.

At the point where init is being run on a view controller, the view hasn't been loaded yet!

浪漫之都 2024-11-04 16:33:43

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

Um I had this issue, and Im new to the whole iOS dev scene. But after looking at my connections inspector (with file's owner) in the interface builder i saw that as I had copied a button it had the previous buttons method assigned to it as well as the new method I had created. I guess that was where the nested aspect of my problem came from, as it was executing 2 different methods both of which pushed a view onto the Nav Controller. I know this has already been answered but I figured I would put this up just in case anyone else had a silly mistake like mine.

迷爱 2024-11-04 16:33:43

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

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

This has already been answered, but I thought this might help others as I got the same error but without using table views. I finally figured out the problem.

I had an existing button whose IBAction invoked a pushViewController. I had created a new button by copying the existing button. The new button also had an action that invoked pushViewController. When the new button was tapped (touch up inside) and the view controller was pushed, I got this error. I deleted the new button, created it from scratch, bound it to the existing outlets and actions, and the error went away.

以为你会在 2024-11-04 16:33:43

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

Ran into the same problem. In my case I was missing a break in the switch statement so two segues were fired at the same time. Easy fix for me.

蓝眼睛不忧郁 2024-11-04 16:33:43

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

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

My problem had to do with the keyboard being active.

This was caused for me by pushing a ViewController from a textField's delegate method:

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

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

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

}

By changing the code to this:

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

        [_textFieldLocation resignFirstResponder]; //adding this line

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

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

}

(adding the line [textField resignFirstResponder];) the problem went away.

Basically the lesson is that you shouldn't modify the navigationController stack if the keyboard is out.

白衬杉格子梦 2024-11-04 16:33:43

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

Recently, I've faced the same problem. The reason was: -I was trying to pop view controller twice by mistake. you can check this crash by setting breakpoints on push and pop View controllers

探春 2024-11-04 16:33:43

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

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

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

1) Perhaps you could try passing the necessary variables as properties before pushing the UIViewController rather than using the init methods with parameters. Most likely you will need these parameters beyond your init method anyway.

Also, in your initWithCoordinates: method you are missing the parameters. Possibly your custom init methods are a part of the problem.

2) Just because you mentioned viewDidLoad -- this method is for initialization after a view has loaded . If you create the UIViewController in code, as it seems you do, you should use loadView to set up your subviews.

浅黛梨妆こ 2024-11-04 16:33:43

这发生在我身上,因为我的 UIControlEvents

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

我必须将 UIControlEventAllTouchEvents 更改为 UIControlEventTouchUpInside 或者,如果您有由于 UIButton 调用而导致的问题。

This was happening for me because of my UIControlEvents

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

I had to change the UIControlEventAllTouchEvents to UIControlEventTouchUpInside or however you want your button to work if you had the issue because of a UIButton call.

把回忆走一遍 2024-11-04 16:33:43

我的解决方案是

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

My Solution was

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

拔了角的鹿 2024-11-04 16:33:43

不知道别人的情况如何。我想大多数使用 StoryBoard 的人都面临着这样的问题。我用的是XIB。

就我而言,问题是,当我使用推送移动到另一个视图时,
使用

 [self.navigationController popViewControllerAnimated:YES];

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

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

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

Don't know about other's. I think most of the People using StoryBoard is facing such Problem. I am using XIB.

In my case The Problem Was, when I was moving to another view using push,
I was also using

 [self.navigationController popViewControllerAnimated:YES];

in the ViewWillDisappear of the current View at the same time. Just remove it and it works fine.

I was using POP, because of the requirement and the Flow.
The Hierarchy was 1 -> 2 ->3

I was on view 2 and wanted to move to view 3. In that case I encountered this error.

溺渁∝ 2024-11-04 16:33:43

就我而言,我既从故事板又以编程方式设置推送转场。希望这对任何人都有帮助

In my case I was both setting the push segue from the storyboard and programatically. Hopefully that'll help anyone

路还长,别太狂 2024-11-04 16:33:43

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

文档明确指出,在重写 viewDidLoad 时应该调用 super,我通过惨痛的教训才了解到这一点。

也许这也可以帮助别人!

I had this error message too, and the navigation bar and navigation controller transitions were weird. My setup was a bunch of Navigation Controllers embedded in a Tab bar Controller. The problem was that I didn't call super.viewDidLoad() in my Tab bar Controller implementation of viewDidLoad.

Calling super is something the docs clearly point out that you should do when overriding viewDidLoad, and I learned this the hard way.

Maybe this can help someone else too!

泡沫很甜 2024-11-04 16:33:43

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

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

I know that this was answered, but it could help others.

I had the same problem, but it was caused because I was using a bad event for an info button.
I was using "UIControlEventAllTouchEvents" and this generated two push of the same view into the navigation controller. The correct event was "UIControlEventTouchUpInside". I'm new to iOS.

无妨# 2024-11-04 16:33:43

这解决了这个问题:
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]嵌套push动画即可
导致导航栏损坏 2014-07-03 11:54:25.406
演示[2840:60b]以意想不到的方式完成导航转换
状态。导航栏子视图树可能会损坏。

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

This resolves the problem:
https://github.com/nexuspod/SafeTransition

If you push (or pop) a view controller with animation(animated:YES) it doesn't complete right away, and bad things happen if you do another push or pop before the animation completes.

To reproduce this bug, try pushing or popping two view controllers at the same time. Example:

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

You will receive this error:

2014-07-03 11:54:25.051 Demo[2840:60b] nested push animation can
result in corrupted navigation bar 2014-07-03 11:54:25.406
Demo[2840:60b] Finishing up a navigation transition in an unexpected
state. Navigation Bar subview tree might get corrupted.

Just add the code files into your project and makes your navigation controller as a subclass of APBaseNavigationController, and you'll be good to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文