在iOS 8中获取heightForRowAtIndexPath下的单元格的引用

E-R*_*die 16 uitableview ios ios8

我目前正在开发一个嵌入UITableView内部的项目UITableViewCell.

我需要做的是禁用UITableView滚动并使其UITableView适合所有行的大小.但是作为UITableView继承UIScrollView,使用Autolayout并不强制在返回时UITableView根据其contentSize(而不是帧)来确定单元格的高度UITableViewAutomaticDimension.

iOS 7解决方案

这很容易实现,直到iOS 7,因为我heightForRowAtIndexPath:使用下面的代码得到了单元格的引用:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
int height = cell.tableView.contentSize.height;

return height;
Run Code Online (Sandbox Code Playgroud)

但是在iOS 8中它给出了BAD_ACCESS,因为iOS 8在调用heightForRowAtIndexPath:之前调用了它cellForRowAtIndexPath:.

iOS 8方法

声明一个属性以保持对单元格的引用:

@property (strong, nonatomic) UITableViewCell *prototypeCell
Run Code Online (Sandbox Code Playgroud)

使用方法将当前单元格引用保存到属性以便使用它:

- (id)prototypeCellatIndexPath:(NSIndexPath *)indexPath {
    NSString *cellID = @"MyCell";

    if (!_prototypeCell) {
        _prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
    }

    return _prototypeCell;
}
Run Code Online (Sandbox Code Playgroud)

获得UITableViewUITableViewCell从原型,并从它的contentSize我得到的高度,我在返回它heighForRowAtIndexPath:从下面的方法:

-(int)heightForThreadAtIndexPath:(NSIndexPath *)indexPath {
    _prototypeCell = [self prototypeCellatIndexPath:indexPath];

    [_prototypeCell.contentView setNeedsLayout];
    [_prototypeCell.contentView layoutIfNeeded];

    int footer = [_prototypeCell.tableView numberOfSections]*_prototypeCell.tableView.sectionFooterHeight;
    int header = [_prototypeCell.tableView numberOfSections]*_prototypeCell.tableView.sectionHeaderHeight;

    int height = ceilf(_prototypeCell.tableView.contentSize.height) + _prototypeCell.tableView.contentOffset.y + _prototypeCell.tableView.contentInset.bottom + _prototypeCell.tableView.contentInset.top + header + footer;
    NSLog(@"%i, %i", (int)ceilf(_prototypeCell.tableView.contentSize.height), height);

    return height;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self heightForThreadAtIndexPath:indexPath];
}
Run Code Online (Sandbox Code Playgroud)

问题

我从prototypeCell返回的contentSize.height是错误的,它与真实的contentSize不匹配UITableView,但是当我在CustomCell Class下记录真实的contentSize时,它显示了正确的contentSize,它与prototypeCell下的不同.

这让我想知道可能我应该尝试将单元格出列到特定状态以获得正确的contentSize,但是日志显示相同的值.

我一直在研究很多并尝试不同的想法,但迄今为止都没有.我不知道是否有人试图与我做类似的事情,并解决了这个问题.如果你给我一个想法或其他什么,那将是非常好的.

iph*_*oid 7

正如您所说,heightForRowAtIndexPath委托方法在自动调用时不会为您提供行的动态高度.相反,您必须明确地将其称为: [self delegateMethod]ie[self tableView:tableView cellForRowAtIndexPath:indexPath];

如果你把主tableView声明为IBOutletlike myTableView,那么即使调用[self.myTableView cellForRowAtIndexPath:indexPath]也行不通!!

我测试了代码,这对我有用:

内部MainTableViewController.m:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return 7;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tableViewCellMain"];
  if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tableViewCellMain"];
  }

  UITableView *tableViewChild = [[UITableView alloc] initWithFrame:CGRectMake(cell.frame.origin.x, cell.frame.origin.y, tableView.frame.size.width, tableView.frame.size.height) style:UITableViewStylePlain];
  [self.cls setNumberOfRows:indexPath.row+1];
  [tableViewChild setDelegate:self.cls];
  [tableViewChild setDataSource:self.cls];
  [tableViewChild setSeparatorStyle:UITableViewCellSeparatorStyleNone];
  [tableViewChild setScrollEnabled:NO];
  [tableViewChild reloadData];
  [cell addSubview:tableViewChild];
  return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
  CGFloat height = cell.frame.size.height;
  for (int i=0; i<cell.subviews.count; i++) {
    UITableView *childTableView = (UITableView*) [cell.subviews lastObject];
    height = childTableView.contentSize.height;
  }

  NSLog(@"%f",height);
  return height;
}
Run Code Online (Sandbox Code Playgroud)

我已经设置了另一个类作为childTableView获取其数据的委托.

内部ChildTableViewController.m:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return self.numberOfRows;
}

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tableViewCellChild"];
  if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tableViewCellChild"];
  }
  [cell.textLabel setText:[NSString stringWithFormat:@"%ld",indexPath.row]];
  UIColor *cellTextColor = [UIColor blackColor];

  switch (indexPath.row)
  {
    case 0: cellTextColor = [UIColor redColor]; break;
    case 1: cellTextColor = [UIColor greenColor]; break;
    case 2: cellTextColor = [UIColor blueColor]; break;
    case 3: cellTextColor = [UIColor magentaColor]; break;
    case 4: cellTextColor = [UIColor purpleColor]; break;
    default: break;
  }
  [cell.textLabel setTextColor:cellTextColor];
  [tableView sizeToFit];
  return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  return 30;
}
Run Code Online (Sandbox Code Playgroud)

你会得到这个图像所示的工作:

UITableView里面的UITableView

我的故事板看起来像这样:

在此输入图像描述

您可以使用任何方式为其生成动态内容,mainTableView并且childTableView不需要使用其他类.


小智 1

我不确定这是否对你有帮助,但我之前必须做这样的事情,我最终将它嵌入到单元格中垂直滚动的 UICollectionView 中,所以它的行为就像 tableview 但其他视图不是 UITableView 这使我能够分别控制每一个

希望这个提示可以帮助你祝你好运