ios7 navigationController pushViewController动画bug

看起来我在navigationController pushViewController方法中发现了一个错误。 为了重新创建它,我采用了示例主详细信息项目并对-didSelectRow:方法进行了一些更改:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController* view = [self.storyboard instantiateViewControllerWithIdentifier: @"view"]; NSDate *object = _objects[indexPath.row]; [view setDetailItem:object]; [self.detailViewController.navigationController pushViewController:view animated:YES]; } 

我还将详细视图的故事板ID更改为“查看”。 这是发生的事情:

当慢慢选择任何主人的行时(当推动画完成时),它可以正常工作: 慢慢选择行

如果在动画仍然显示时选择任何行,则详细视图将变为非活动状态(显示在错误之前使用push方法调用的最后一行),并且只有导航栏显示新视图的推送动画: 快速选择行

发生这种情况时,您会在调试器输出中收到一些警告:

 Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted. nested push animation can result in corrupted navigation bar Unbalanced calls to begin/end appearance transitions for . 

这是令人讨厌的部分:如果你回到详细视图的导航栏然后在Master的tableview中选择一个不同的行,或者在详细信息中返回两次应用程序崩溃

 Can't add self as subview 

但是,如果您在ios6上运行相同的代码,它可以正常工作,没有任何问题或警告。

当前解决方案

用动画调用方法:NO似乎没有任何问题,显然没有推动画。

另一个解决方案是在Master中设置一个布尔值,在调用push方法时将其设置为false,并从Detail in Detail的viewDidAppear中将其设置为true。 这样,您可以在调用push方法时检查该值。 缺点:如果您尝试快速选择同一行,tableView可能会显得滞后,如果您快速选择另一行然后它将不会显示在详细信息中但它将在主表视图中被选中并突出显示,您可以保存所选行的索引并更改代码中的选择,但这会导致闪烁的行突出显示。

这两个解决方案都涉及一些妥协,所以我想找到另一种处理方法。 还有更好的解决方案吗?

经过一些测试后,似乎在ios6中,当一个tableview单元被选中并且push被调用时,tableview将.allowsSelection设置为NO直到push结束。

这可以通过在didSelectRowAtIndexPath:的push方法之后将.allowsSelection设置为NO并在详细信息视图的didAppear:方法中进行回调来在didAppear:轻松复制,我们在主视图中将tableview的.allowsSelection设置为YES

虽然这种方法非常好,但我发现在一个接一个地快速选择两个不同的单元格时会发现它有点烦人,第二个单元格会被忽略。

所以我设置了如果在推动动画尚未结束时选择另一个单元格,我将保存对新视图的引用,并在第一个动画结束后立即推送它。 通过这样做,tableView在我看来似乎更具响应性。

你背后的原因是推动一个视图控制器,而另一个没有完全推动(日志已警告你这样做)。

推动动画应该花费大约0.4秒,因此用户必须足够快以在0.4秒内敲击另一行,是的,这是适用的,但不是正常行为。

您可以做的是使用-didSelectRow:方法中的以下代码将动画时间编辑为小于0.4秒(可能是0.1或0.2):

 DetailViewController* view = [self.storyboard instantiateViewControllerWithIdentifier: @"view"]; NSDate *object = _objects[indexPath.row]; [view setDetailItem:object]; [UIView beginAnimations:@"ShowDetails" context: nil]; [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.2]; [self.detailViewController.navigationController pushViewController:view animated:NO]; [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:NO]; [UIView commitAnimations]; 

希望能帮助到你 :)