Objective c EXC\u访问权限不正确,高度为ROWATINDEXIOS

Objective c EXC\u访问权限不正确,高度为ROWATINDEXIOS,objective-c,ios,uitableview,Objective C,Ios,Uitableview,我正在开发一个应用程序,其中有一个自定义的UITableViewCell子类。我想根据单元格内的文本动态设置单元格的高度。我尝试在heightForRowAtIndexPath方法中这样做。但是我有一些问题,下面的代码导致EXC_BAD_ACCESS(代码=2地址=0xb7ffffcc)错误 如果我有: - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

我正在开发一个应用程序,其中有一个自定义的UITableViewCell子类。我想根据单元格内的文本动态设置单元格的高度。我尝试在heightForRowAtIndexPath方法中这样做。但是我有一些问题,下面的代码导致EXC_BAD_ACCESS(代码=2地址=0xb7ffffcc)错误

如果我有:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    return 100;
}
它起作用了


这行代码似乎崩溃了:
PostCell*cell=(PostCell*)[tableView cellforrowatinexpath:indexath],我不知道为什么。我曾试图建立干净和重置模拟器,但都不起作用。知道为什么会这样吗

我试图重现这个问题。结果是,在
heightforrowatinexpath
内部调用
cellforrowatinexpath:
会导致递归调用
heightforrowatinexpath
。下面是在3个递归步骤之后的堆栈回溯提取:

frame #0: 0x000042d0 DocInteraction`-[DITableViewController tableView:heightForRowAtIndexPath:] + 48 at DITableViewController.m:262
frame #1: 0x0054f688 UIKit`-[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 3437
frame #2: 0x0055040f UIKit`-[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:] + 144
frame #3: 0x00551889 UIKit`-[UITableViewRowData numberOfRows] + 137
frame #4: 0x00553dac UIKit`-[UITableViewRowData globalRowsInRect:] + 42
frame #5: 0x003f82eb UIKit`-[UITableView(_UITableViewPrivate) _visibleGlobalRowsInRect:] + 177
frame #6: 0x004001e6 UIKit`-[UITableView cellForRowAtIndexPath:] + 113
frame #7: 0x000042f2 DocInteraction`-[DITableViewController tableView:heightForRowAtIndexPath:] + 82 at DITableViewController.m:262
frame #8: 0x0054f688 UIKit`-[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 3437
frame #9: 0x0055040f UIKit`-[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:] + 144
frame #10: 0x00551889 UIKit`-[UITableViewRowData numberOfRows] + 137
frame #11: 0x00553dac UIKit`-[UITableViewRowData globalRowsInRect:] + 42
frame #12: 0x003f82eb UIKit`-[UITableView(_UITableViewPrivate) _visibleGlobalRowsInRect:] + 177
frame #13: 0x004001e6 UIKit`-[UITableView cellForRowAtIndexPath:] + 113
frame #14: 0x000042f2 DocInteraction`-[DITableViewController tableView:heightForRowAtIndexPath:] + 82 at DITableViewController.m:262
frame #15: 0x0054f688 UIKit`-[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 3437
frame #16: 0x0055040f UIKit`-[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:] + 144
frame #17: 0x00551889 UIKit`-[UITableViewRowData numberOfRows] + 137
frame #18: 0x003ff66d UIKit`-[UITableView noteNumberOfRowsChanged] + 119
frame #19: 0x003ff167 UIKit`-[UITableView reloadData] + 764
最后程序崩溃了。在我的模拟器上,这发生在回溯轨迹大约57000层深的时候


旧答案(没有错,但没有解释 EXC_坏访问):

问题是

[tableView cellForRowAtIndexPath:indexPath]
对于当前不可见的行,返回
nil
。表视图仅分配显示当前可见行所需的单元格数量。滚动表格视图时,这些单元格将被重新使用

但是,在显示任何行之前,表视图的所有单元格都会调用
heightforrowatinexpath


因此,您不应该从表视图单元格中获取文本来计算
heightforrowatinexpath
中的高度。您应该从数据源获取文本。

单元格之前调用tableView HeightForRowatineXpath
,在显示单元格之前,需要先计算高度


您应该从您的数据源获取
文本,而不是从
单元格获取

我也遇到过类似的问题,只是为了分享我现在所做的对我来说很好的工作

CGFloat mycell_height;

- (void)viewDidLoad
{
    [super viewDidLoad];
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCell"];
    mycell_height = cell.frame.size.height;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  return mycell_height; //assuming all cells are the same
}

希望这能帮助像我这样的iOS编程新手了解这一点:-)

在这种情况下,您应该调用UITableViewDataSource方法来获取indexPath的单元格,而不是UITableView的CellForRowatineXpath:method,因为在第一次调用tableView:HeightForRowatineXpath:HeightForRowatineXpath时,表中没有任何单元格桌面视图

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
    PostCell *cell = (PostCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];

    CGSize postTextSize;
    if (![cell.postText.text isEqualToString:@""]) {
    postTextSize = [cell.postText.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(cell.postText.frame.size.width, 200)];
    } else {
        postTextSize = CGSizeMake(cell.postText.frame.size.width, 40);
    }

    return postTextSize.height + cell.userName.frame.size.height + 10;
}
它工作正常,不会导致EXC\U BAD\U访问异常。

SWIFT:

使用此选项可了解表何时加载:

extension UITableView {
    func reloadData(completion: ()->()) {
        UIView.animateWithDuration(0, animations: { self.reloadData() })
            { _ in completion() }
    }
}
创建一个布尔值

var tables_loaded = Bool(false)
然后在viewDidLoad中:

tableView.reloadData {
    tables_loaded = true
    // call functions or other stuff regarding table manipulation.
    // tableView.beginUpdates()
    // tableView.endUpdates()
}
然后在

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
            if tables_loaded {
                let cell = tableView.cellForRowAtIndexPath(indexPath)
                 // Do your magic here!
             }

}

返回nil的方法是通过什么机制导致EXC_坏访问的?@grahamparks:好问题!我试图重现这个问题,并将信息添加到我的答案中。@Anders:不客气。-根据grahamparks的评论,找出问题的确切原因很有趣。感谢@MartinR的调查。你能编辑一下答案吗?这样递归问题就可以在上面描述了。应返回nil,并且不应导致EXC\u访问错误。我几乎错过了你添加的重要递归分析。不相关,但
Bool(false)
似乎没用:
false
是正确的,Swift可以推断其类型。我很想知道为什么你会用
Bool
initialiser?@vrwim设置
var
,因为我是Swift的noob.=)这对我来说是可行的,但这意味着UITableViewDataSource方法在tableview中创建单元格之前就可以工作,对吗@忍者罗杰
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
            if tables_loaded {
                let cell = tableView.cellForRowAtIndexPath(indexPath)
                 // Do your magic here!
             }

}