所有这些自动布局更新方法有什么区别? 都需要吗?

在下面的代码中,这四个方法被称为布局推理。 我有点困惑,为什么他们都需要,但是他们做了什么不同的事情。 他们在这个过程中使用自动布局使单元格的高度dynamic化。 (从这个问题从这个知识库采取)。

[cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; [cell.contentView setNeedsLayout]; [cell.contentView layoutIfNeeded]; 

这是从这个单元格的代码块的高度:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; [cell updateFonts]; NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row]; cell.titleLabel.text = [dataSourceItem valueForKey:@"title"]; cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"]; cell.bodyLabel.preferredMaxLayoutWidth = tableView.bounds.size.width - (kLabelHorizontalInsets * 2.0f); [cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; [cell.contentView setNeedsLayout]; [cell.contentView layoutIfNeeded]; CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; return height; } 

但是他们有什么不同呢? 为什么他们都需要?

布局

假设你将视图逻辑封装在一个UIView子类中,并将其SomeView 。 这意味着SomeView应该知道如何布局自己,也就是如何在其中放置一些其他的视图(你也可以创build一个不使用任何子视图的视图,但这超出了普通开发人员的需求)。

此布局由[SomeView layoutSubviews] 。 你可以select重写它:

 subview.frame = CGRectMake(100 + shiftX, 50 + shiftY, 250 + shiftX - paddingRight, ... // Oh no, I think I didn't do it right. 

但你很less需要这样做。 在Cocoa Touch的黑暗时代,这种手工布局是普遍的,但现在我说99%的布局可以覆盖自动布局。

系统需要知道什么时候应该调用[UIView layoutSubviews] 。 这显然是在您第一次绘制视图时完成的,但是也可能在超视图框架更改时调用。 这里有一个详细的解释 。

所以系统经常调用[view layoutIfNeeded]也可以随时调用它,但是只有在某个事件已经调用了[view setNeedsLayout]或者手动调用了这个事件,才会产生效果,就像这种情况一样。

约束

Auto Layout (在文档 [SomeView layoutSubviews]这种方式大写)就是这样调用的,因为它是从[ UIView [SomeView layoutSubviews]inheritance而来的[SomeView layoutSubviews] ,并用约束来描述你的子视图的位置。

当使用自动布局时,系统将在每个布局阶段执行对[view updateConstraintsIfNeeded]调用。 但是,只有标志[view setNeedsUpdateConstraints]; 被设置,该方法调用-updateConstraints (这是真正的工作)。

如果您不使用自动布局,这些方法是不相关的。

你可以像这个例子一样实现它。

你的例子

很less需要直接调用-layoutIfNeeded-layoutIfNeeded ,因为UI引擎会在每个布局过程中自动执行此操作。 但在这种情况下,作者select立即打电话给他们; 这是因为由此产生的高度现在是需要的,而不是将来的某个时刻。

这种更新单元格高度的方法似乎是正确的。 请注意, cell可能是新创build的单元格,因此尚未添加到视图层次结构中; 这并不影响其自身布局的能力。

结论

在您的自定义视图中,从以下选项开始,从最“通用”到最“自定义”:

  1. 在创build视图时创build约束(手动或在IB中)
  2. 如果以后需要更改约束,请覆盖-updateConstraints
  3. 如果有一个复杂的布局,无法用上述方法描述,请覆盖-layoutSubviews

在代码中改变可能使你的视图的约束改变的东西,调用

 [view setNeedsUpdateConstraints]; 

如果您立即需要结果,也请致电

 [view updateConstraintsIfNeeded]; 

如果代码更改视图的框架使用

 [view setNeedsLayout]; 

最后如果你想立即结果,请致电

 [view layoutIfNeeded]; 

这就是为什么在这种情况下所有四个电话都是必需的。

其他材料

请参阅高级自动布局工具箱 objc.io问题#3中的详细说明