我在标签栏控制器中有 3 个视图控制器。单击任何选项卡都会在导航堆栈中加载其根视图控制器。
例如选项卡 1、选项卡 2 和选项卡 3。
导航堆栈中的第二个视图控制器 (tab2VC2) 有一个 tableView。
单击 tab2 在 tab2 中显示 VC,然后点击 tab1,尝试转到其根 VC。然后应用程序崩溃说
[用户详情VC
表视图:cellForRowAtIndexPath:]:
消息发送到已释放的实例
0xe0a23b0
如果我用动画 popToRootVC 那么就可以了。我发现在调用tableView.reloadData的地方调用了tab2VC2中的viewDidAppear,然后dealloac,似乎同时reloadData开始工作,表被释放。如果是动画,它需要一些时间,所以它不会崩溃。但如果没有动画,它就会崩溃。
你认为这是 iPhone 的 bug 吗?或者我做错了?由于弹出到根控制器有一个没有动画的选项,它应该可以工作,不是吗?
#pragma mark Tab bar controller delegate
- (void)tabBarController:(UITabBarController *)tbController didSelectViewController:(UIViewController *)viewController {
int i = tbController.selectedIndex;
NSArray *mycontrollers = tbController.viewControllers;
[[mycontrollers objectAtIndex:i] popToRootViewControllerAnimated:NO];
}
我认为这是 UIKit 中的一个错误,或者至少是一个弱点,但我已经在上面花了半天时间了,所以我现在不打算用示例代码编写它并向 Apple 报告。如果其他人愿意这样做,我将不胜感激。
这就是我认为幕后发生的事情。您有一个 UITableViewController,我们将其称为 myTable,位于 UINavigationController 的堆栈上,并且该导航堆栈是隐藏的,因为它位于未选择的选项卡或其他内容上。然后,你调用[myTable.tableView reloadData],iOS巧妙地优化了not立即重新加载数据,因为如果它位于隐藏选项卡上,用户无论如何都不会看到它。相反,重新加载请求会被推迟并存储在某处以供视图显示时使用。但在显示之前,您需要将 myTable 从导航堆栈中弹出。当显示 myTable 的原始选项卡时,会执行重新加载请求,但其数据源不再存在,因此这是一个错误的访问。
现在,根据我对 UITableViewController 子类的测试,该子类使用自动提供的 tableView 属性(不是从 NIB 文件加载),当 myTable 解除分配时,UITableView 不会被解除分配,如上述情况。这很好,除了 UITableViewController 的默认 dealloc 实现不会清除 UITableView 的 dataSource 属性(该属性由 init 的默认实现设置)。
因此,可能有一些好的解决方法,例如自己推迟对 reloadData 的请求,但我能想到的最简单的方法是将其放入 UITableViewController 子类的实现中:
- (void)dealloc {
...
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
[super dealloc];
}
任何额外的智慧都将受到欢迎。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)