具有自动布局和附件视图的自定义 UITableViewCell

Custom UITableViewCell with auto layout and accessory view

我有一个自定义 table 视图单元格,它使用自动布局并有一个公开指示器作为辅助视图。 第一次显示时屏幕上的单元格大小完全错误:

如您所见,该单元格占用了大约 1.5 个屏幕 space:

但是,如果我旋转设备并向后旋转,它看起来很好:

正如你在这里看到的,我没有做任何复杂的事情:

我有一个非常不理想的解决方法:

-(void)viewDidAppear:(BOOL)animated 
{
    [super viewDidAppear:animated];
    [self.tableView reloadData];
}

但这显然会在您第一次看到屏幕时引起 'flash'。在更复杂的情况下,闪光会更加明显。

我有另一种解决方法,但这会导致自动布局异常:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    BasicCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BasicCell" forIndexPath:indexPath];
    cell.basicLabel.text = @"Hello this is just some text that should get the label to go over multiple lines";
    [cell.basicLabel layoutIfNeeded];
    return cell;
}

异常:

至少这个方法不给我UI闪

如果我删除附件视图,它实际上工作得很好。

更新:我已将示例项目添加到 github: https://github.com/fwaddle/TableCellAccessoryTest

更新 #2:事实证明,解决此错误的另一项工作是在代码中布局单元格。我只是尝试在代码中做同样的事情,它没有发出警告并且工作正常。看起来像 IB 错误。

有什么解决这个问题的想法吗? 谢谢。

实现以下委托方法,因为这解决了我的问题。

- (void)tableView:(UITableView *)tableView   
willDisplayCell:(UITableViewCell *)cell 
forRowAtIndexPath:(NSIndexPath*)indexPath

A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.

将此代码添加到您的 tableViewController:

 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell   forRowAtIndexPath:(NSIndexPath *)indexPath{

    BasicCell *basicCell = (BasicCell *)cell;
    basicCell.basicLabel.text = @"Hello this is just some text that should get the label to go over multiple lines";

}

因此,即使在代码中创建约束有时也无法解决此问题。看来你还需要一些改变。在您的自定义 table 单元格中添加以下内容,特别是如果您根据单元格的内容更改配件类型(例如复选标记):

-(void) setAccessoryType:(UITableViewCellAccessoryType)accessoryType {
  [super setAccessoryType:accessoryType];
  [self setNeedsUpdateConstraints];
}

同时删除情节提要中的原型单元并改为注册您的 class:

-(void) viewDidLoad {
  [super viewDidLoad];
  [self.tableView registerClass:[MyCustomCell class] forCellReuseIdentifier:@"MyCustomCell"];
}

我偶尔发现我仍然需要在 cellForRowAtIndexPath:

中强制标签(尤其是看起来多行的标签)重新布局
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCustomCell" forIndexPath:indexPath];
  cell.customLabel.text = .....
  [cell.customLabel layoutIfNeeded];
  return cell;
}

以上所有内容都解决了我的问题,所以我希望它们对其他人有用,并且您不要在这上面浪费大量时间。

我仍然没有收到 Apple 关于错误报告的任何回复,但我认为这很正常。