2014-09-26 117 views
3

当我在tableView结束滚动之前给我的tableView一个很好的滑动并按下“返回”按钮时,我的应用程序崩溃。我试过以下内容:当tableView仍在滚动时,popToRootViewController崩溃

- (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 = niltextFieldDidEndEditing解决了这一问题。谢谢大家的答案!

+0

你能提供你的viewController一些额外的信息层次? – 2014-09-26 13:39:11

+0

检查这是否可以帮助你http://stackoverflow.com/questions/19087867/ios-7-on-textfield-did-change-the-firstresponder-my-application-is-crashing – iOSdev 2014-09-26 13:41:54

回答

2

这是UITableView的奇怪行为。解决此问题的最简单方法是在您调用函数popToRootViewControllerAnimated之前将dataSourcedelegate属性UITAbleView设置为零。此外,您可以使用更常见的解决方案,并将将属性设置为零的代码添加到-dealloc方法中。另外你不需要-killScroll方法。

经过短时间的研究,我意识到问题所在。这种不寻常的行为出现在iOS 7中。其超级视图保留的滚动视图可能会在委托发布后将消息发送给委托。这是由于-removeFromSuperview执行UIScrollView触发器-setContentOffset:,并最终发送消息给代表。

+0

我曾尝试设置'dataSource'并在结束前将“委托”改为零,但我仍然遇到了崩溃。 Thx的信息btw :) – Yoko 2014-09-26 14:37:45

1

setContentOffset方法不会帮你,尝试设置

sellersTableView.dataSource = nil; 

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

+0

试过这个,但没有运气。仍然崩溃与相同的错误。 Thx虽然! – Yoko 2014-09-26 14:39:29

0

我不认为设置tableView(或它的委托)为零是问题。您应该能够单独执行dismissViewControllerAnimated或popToRootViewController,而无需通过这种方式修改tableView。

所以这个问题很可能是由于同时调用这两个方法(并且带有animated = YES),并且这样做要求您的viewController设置执行一些不自然的操作。

看起来像点击一个“关闭”按钮,你都弹出的UINavigationController,以及解散模态viewController

在这样做时,您将忽略可能由navigationControllertopViewController表示的模式viewController(因此top vc持有对模态vc的引用)。并且您正试图通过popToRootViewController方法调用来终止顶层vc。而且你正在使用animated = YES来完成这两件事,这意味着它们需要一些时间才能完成,并且你无法确定每次完成的时间(即不能确定何时调用dealloc)。

根据你的需要,你可以做几件事情之一。

考虑添加一个委托属性到你的模态vc。关闭模态vc,并在模态vc的completionBlock中告诉其代表它已完成解散。在这一点上,调用popToRootViewController(因为在这一点上,你可以确定模式已经消失,滚动没有中断)。

如果它是你的navController,它是以模态方式呈现的,那么以相反的顺序进行操作。通知代表已完成流行操作,然后进行模式解雇。

+0

我删除了'[self dismissViewControllerAnimated:YES completion:nil];',那是我的错误。但除此之外,错误仍然存​​在,并导致我的应用程序崩溃。 Thx虽然答案! – Yoko 2014-09-26 14:41:39

2

就在dealloc方法的开头添加以下行:

sellersTableView.delegate = nil; 
sellersTableView.dataSource = nil; 

没有必要使用黑客喜欢你killScroll方法。

另外,我看不出为什么你要打电话popToRootViewControllerdismissViewController。 如果您关闭嵌入在导航控制器中的视图控制器,导航控制器本身以及所有包含的视图控制器将被释放。

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

+0

尝试了你的方法,但它仍然崩溃,同样的错误。关于我的'popToRootViewController'&'dismissViewController',你是对的,那简直是愚蠢的。 – Yoko 2014-09-26 14:35:02

+0

在这种情况下,请提供代理和数据源方法的代码。 – hybridcattt 2014-09-27 17:23:15

1

更改您closeViewController像下面,看看作品

  • (无效)closeViewController

{

sellersTableView.dataSource = nil; 
sellersTableView.delegate = nil; 
[self.navigationController popToRootViewControllerAnimated:YES]; 
[self dismissViewControllerAnimated:YES completion:nil]; 

}

+0

Thx为您的答案! Buuuuuut,尝试了它,并得到相同的结果。 – Yoko 2014-09-26 20:17:45

+0

我在想的是你没有提供sellersTableView到你的xib/storyboard的连接。 – 2014-09-26 20:34:16

+0

对不起,这是全部编码。没有xib或故事板... – Yoko 2014-09-27 01:00:24