看起来我发现了navigationController pushViewController方法中的一个bug。为了重现它,我拿取了示例master detail项目并对-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更改为“view”。以下是发生的情况:
当缓慢选择主控制器的任何行(推动动画完成时)时,它工作正常: 如果在动画仍在显示时选择任何行,则详细视图将变得无效(显示推方法之前调用的最后一行),只有导航栏显示新视图的推送动画: 当这种情况发生时,您会在调试器输出中收到一些警告:
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 <DetailViewController: 0x8a6e070>.
这里有个棘手的问题:如果你回到详细视图的导航栏,然后在主表视图中选择不同的行,或者在详细视图中返回两次,应用程序会崩溃。
Can't add self as subview
但是,如果在iOS6上运行相同的代码,则没有任何问题或警告。
当前解决方案:
调用animated:NO方法似乎可以正常工作,显然没有推送动画。
另一种解决方案是在主页面中设置boolean值,并在从详细页面的viewDidAppear中将其设置为true。这样,您在调用push方法时可以检查该值。缺点是:如果您快速选择同一行,则tableView可能会出现滞后,如果您快速选择不同的行,则不会在详细信息中显示,但会在主表视图中被选中并突出显示,您可以保存所选行的索引并在代码中更改选择,但这会导致行突出显示闪烁。
这两个解决方案都涉及一些妥协,因此我希望找到另一种处理方式。有更好的解决方案吗?