当tableView仍在滚动时,popToRootViewController崩溃

时间:2014-09-26 13:25:34

标签: ios objective-c uitableview uiscrollview

当我对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 = nildelegate = nil放入textFieldDidEndEditing可以解决问题。谢谢大家的答案!

5 个答案:

答案 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。

另外,我无法理解为什么要同时拨打popToRootViewControllerdismissViewController。 如果您关闭嵌入在导航控制器中的视图控制器,则将释放导航控制器本身以及所有包含的视图控制器。

在你的情况下,你会有奇怪的动画。

答案 2 :(得分:1)

setContentOffset方法无法帮助您,请尝试设置

sellersTableView.dataSource = nil;

viewWillDisappear方法中的某处。 当然,这不是一个好习惯。

答案 3 :(得分:1)

如下所示更改closeViewController并查看是否有效

  • (void)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是以模态方式呈现的,那么按相反的顺序执行此操作。通知代表弹出操作已完成,然后进行模态解雇。

相关问题