iOS:popViewController出乎意料的行为
我一直在寻找一个解决scheme的互联网。 我找不到任何东西 所以:我正在使用UINavigationController。 我推着两个UIViewControllers到它。 在第二个推ViewController我执行此代码:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { NSLog([error localizedDescription]); [self.navigationController popViewControllerAnimated:YES]; }
预期发生的事情是,最后推送的ViewController消失。 在这个应用程序,我在less数地方这样做,它在这个非常的ViewController的任何地方都能正常工作。 会发生什么是只有后退button离开屏幕(animation),但其他一切保持在屏幕上。 在控制台输出中,当这条线执行时,两个东西被打印出来:
2011-03-14 16:32:44.580 TheAppXY [18518:207]嵌套的stream行animation会导致导航栏损坏
2011-03-14 16:32:53.507 TheAppXY [18518:207]完成处于意外状态的导航转换。 导航栏子视图树可能会损坏。
两条错误消息我找不到任何信息。 我正在使用XCode 4和iOS SDK 4.3。 也许任何人都可以帮助我解决这个问题。
我在我的代码中遇到了类似的情况,消息说:
嵌套的推动animation可能会导致导航栏损坏
完成处于意外状态的导航转换。 导航栏子视图树>可能会损坏。
我对这个问题的发现是,我一个接一个地连续推动两个视图控制器,并且都是animation的。
在你的情况下,似乎你可能会popup多个视图控制器与animation一个接一个。
因此,当一个视图正在进行animation时,您不应该在另一个视图上开始animation。
我还发现,如果我在一个视图上禁用了animation,错误信息就消失了。
在我的情况下,这是stream程逻辑的问题,因为我不打算一个接一个地推动2个视图控制器。 一个在开关柜逻辑内被推入,另一个在结束后被推入。
希望这有助于某人。
你可以随时得到这个,你试图在viewDidAppear
之前popup。 如果你设置了一个标志,那么只需在viewDidAppear
检查该标志,你就不会有问题。
我已经创build了一个UINavigationController的替代品,它将为您排队animation,并完全避免这个问题。
从BufferedNavigationController中抓取它
我也有这个问题,这是什么导致我的:
- 在RootViewController中,我使用了几个UISegmentedControl对象来确定下一个加载哪个视图。
- 在(sub / 2nd)视图中,我popup(通过使用“后退”button)回到RootViewController。
- 在RootViewController中,我正在处理viewWillAppear以将每个UISegmentedControl对象重置为-1的selectedSegmentIndex(意味着没有看起来“按下”的段)。
- 这个“重置”触发了我的每个UISegmentedControl对象来触发它们相关的(和单独的)IBAction。
- 因为我没有处理-1的“select”,所以我有多个方法在同一时间开火,都试图推动不同的观点。
我的修复? 我收紧了我的if … then语句,并保留在selectedSegmentIndex == -1时执行我的UISegmentedControl IBActions中的任何代码。
我仍然不确定为什么我得到“stream行”animation错误,而不是“推”错误,但至less弄清了我的错误,并得到修复!
希望这可以帮助别人!
是的,不幸的是苹果没有同步UINavigationController的animation。 安德鲁的解决scheme非常好,但如果你不想覆盖它的全部function,有一个更简单的解决scheme,重写这两个方法:
// 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 ]; }
并创build一个名为waitingList的NSMutableArray实例variables,就完成了。
当我使用故事板时,这个问题发生在我身上。 我犯了一个错误:我有一个用来执行SegueWithIdentifier的动作的UIButton。 所以我链接与其他ViewController与推button,所以发生这个问题。
解决方法:链接UIButton中的button动作,并链接两个ViewController之间的push segue。
结合MilGra和Andrew的答案给了我一些可靠的工作,是一个简单的插入UINavigationControllerreplace。
这改进了MilGra的答案,使其能够与推送和popup工作,但比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