所有这些自动布局更新方法有什么区别? 都需要吗?
在下面的代码中,这四个方法被称为布局推理。 我有点困惑,为什么他们都需要,但是他们做了什么不同的事情。 他们在这个过程中使用自动布局使单元格的高度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的单元格,因此尚未添加到视图层次结构中; 这并不影响其自身布局的能力。
结论
在您的自定义视图中,从以下选项开始,从最“通用”到最“自定义”:
- 在创build视图时创build约束(手动或在IB中)
- 如果以后需要更改约束,请覆盖
-updateConstraints
。 - 如果有一个复杂的布局,无法用上述方法描述,请覆盖
-layoutSubviews
。
在代码中改变可能使你的视图的约束改变的东西,调用
[view setNeedsUpdateConstraints];
如果您立即需要结果,也请致电
[view updateConstraintsIfNeeded];
如果代码更改视图的框架使用
[view setNeedsLayout];
最后如果你想立即结果,请致电
[view layoutIfNeeded];
这就是为什么在这种情况下所有四个电话都是必需的。
其他材料
请参阅高级自动布局工具箱 objc.io问题#3中的详细说明
- 使用“自动布局”,如何使同一“行”上的两个标签在宽度上dynamic变化(根据每个标签的宽度进行调整)?
- 是否有可能在UIScrollView放大和缩小UIImageView,但坚持自动布局居中?
- UITableView中的dynamicUIImageView大小
- 自动布局具有dynamic高度子视图的UIScrollView
- UIStackView里面的UITextview
- 为UIScrollView设置约束
- UITableView tableFooterView显示在UITableView的顶部 – 错误
- 如何将宽度等同于NSLayoutConstraint的某些UIViews?
- 如何在自动布局的横向模式下设置水平文本字段?