当我对tableView进行了很好的滑动并在tableView结束滚动之前按下“返回”按钮,我的应用程序崩溃了。我尝试了以下内容:
- (void) closeViewController
{
[self killScroll];
[self.navigationController popToRootViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)killScroll
{
CGPoint offset = sellersTableView.contentOffset;
[sellersTableView setContentOffset:offset animated:NO];
}
那不起作用,同样崩溃。我不明白为什么,我得到的错误如下:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
这意味着当所有内容都已被释放时,tableView仍在请求一个单元格。没有意义。 然后我尝试了这个:
- (void) closeViewController
{
[self.navigationController popToRootViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)dealloc
{
sellersTableView.dataSource = nil;
sellersTableView.delegate = nil;
sellersTableView = nil;
}
给我同样的错误。有什么想法吗?
更新 我的委托方法
创建
if (textField == addSellerTextField) {
sellersTableView = [[UITableView alloc] initWithFrame:CGRectMake(addSellerTextField.frame.origin.x + addSellerTextField.frame.size.width + 10, addSellerTextField.frame.origin.y - [self heightForTableView] + 35, 200, [self heightForTableView])];
sellersTableView.delegate = self;
sellersTableView.dataSource = self;
sellersTableView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.05];
sellersTableView.separatorColor = [[UIColor grayColor] colorWithAlphaComponent:0.15];
sellersTableView.rowHeight = 44;
sellersTableView.layer.opacity = 0;
[self.companyView addSubview:sellersTableView];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{sellersTableView.layer.opacity = 1;} completion:nil];
}
的cellForRowAtIndexPath
if (tableView == sellersTableView) {
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor clearColor];
if ([sellersArray count] > 0) {
cell.textLabel.text = [sellersArray objectAtIndex:indexPath.row];
} else {
UILabel *noSellersYetLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, sellersTableView.frame.size.width, [self heightForTableView])];
noSellersYetLabel.text = @"no sellers yet";
noSellersYetLabel.textAlignment = NSTextAlignmentCenter;
noSellersYetLabel.textColor = [UIColor grayColor];
[cell addSubview:noSellersYetLabel];
sellersTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
}
去除
- (void) textFieldDidEndEditing:(UITextField *)textField
{
if (textField == addSellerTextField) {
[self updateSellers:textField];
}
}
- (void)updateSellers:(UITextField *)textField
{
[textField resignFirstResponder];
[self hideSellersTableView];
}
- (void)hideSellersTableView
{
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{sellersTableView.layer.opacity = 0;} completion:nil];
sellersTableView.dataSource = nil;
sellersTableView.delegate = nil;
[sellersTableView removeFromSuperview];
sellersTableView = nil;
}
解
显然,将dataSource = nil
和delegate = nil
放入textFieldDidEndEditing
可以解决问题。谢谢大家的答案!
答案 0 :(得分:2)
这是UITableView的奇怪行为。解决此问题的最简单方法是,在调用函数dataSource
之前,将delegate
的{{1}}和UITAbleView
属性设置为nil。此外,您可以使用更常见的解决方案,并将设置属性的代码添加到popToRootViewControllerAnimated
方法中。此外,您不需要-dealloc
方法。
经过短暂的研究后,我意识到问题所在。这种不寻常的行为出现在iOS 7中。其超级视图保留的滚动视图可以在委托发布后向委托发送消息。它发生在-killScroll
实现-removeFromSuperview
触发器UIScrollView
的最后,并最终向委托发送消息。
答案 1 :(得分:2)
只需在dealloc
方法的开头添加以下行:
sellersTableView.delegate = nil;
sellersTableView.dataSource = nil;
不需要像killScroll方法一样使用hack。
另外,我无法理解为什么要同时拨打popToRootViewController
和dismissViewController
。
如果您关闭嵌入在导航控制器中的视图控制器,则将释放导航控制器本身以及所有包含的视图控制器。
在你的情况下,你会有奇怪的动画。
答案 2 :(得分:1)
setContentOffset
方法无法帮助您,请尝试设置
sellersTableView.dataSource = nil;
viewWillDisappear
方法中的某处。
当然,这不是一个好习惯。
答案 3 :(得分:1)
如下所示更改closeViewController并查看是否有效
{
sellersTableView.dataSource = nil;
sellersTableView.delegate = nil;
[self.navigationController popToRootViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
答案 4 :(得分:0)
我不认为将tableView(或它的委托)设置为nil是个问题。您应该能够单独执行dismissViewControllerAnimated或popToRootViewController,而无需以这种方式修改tableView。
所以问题很可能是由于同时调用这两种方法(并且使用animated = YES),并且这样做会要求你的viewController设置做一些不自然的事情。
通过点按“关闭”按钮,您可以弹出rootViewController
的{{1}},同时取消模式UINavigationController
。
这样做,你就会解雇一个模式viewController
,它可能由viewController
的{{1}}呈现(所以top vc持有对modal vc的引用)。你试图通过popToRootViewController方法调用杀死顶级vc。你正在使用topViewController
做这两件事,这意味着他们需要一些时间才能完成,你无法确定每次完成时(即你不能确定何时会调用dealloc)。
根据您的需要,您可以执行以下操作之一。
考虑向模态vc添加委托属性。关闭模态vc,并在模态vc的completionBlock中告诉其委托它已完成解雇。此时调用popToRootViewController(因为此时你可以确定模态已经消失并且滚动没有被中断)。
如果你的navController是以模态方式呈现的,那么按相反的顺序执行此操作。通知代表弹出操作已完成,然后进行模态解雇。