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

 方彦 发布于 2023-02-13 16:55

在下面的代码中,调用这四种方法进行布局推理.我有点困惑为什么所有这些都是需要的,以及它们彼此不同的做法.它们在过程中用于通过自动布局使单元格的高度变为动态.(来自该库从这个问题.)

[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;
}

但他们的做法有何不同?他们为什么都需要?

1 个回答
  • 布局

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

    这种布局是通过[SomeView layoutSubviews].您可以选择覆盖它:

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

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

    系统需要知道何时应该呼叫[UIView layoutSubviews].它显然是在您第一次需要绘制视图时完成的,但是每当超视图帧发生变化时也可以调用它.这是一个详细的解释.

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

    约束

    自动布局(大写这种方式中的文档),因为你要离开了被称为这样的[SomeView layoutSubviews],因为它是从继承UIView和描述,而不是表示你的子视图的位置约束.

    使用自动布局时,系统将[view updateConstraintsIfNeeded]在每个布局过程中执行调用.但是,只有[view setNeedsUpdateConstraints];设置了标志,方法-updateConstraints才会调用(执行实际工作).

    如果您不使用自动布局,则这些方法不相关.

    您可以像在此示例中一样实现它.

    你的榜样

    这是很少需要调用 -layoutIfNeeded-updateConstraintsIfNeeded直接,因为UI引擎将在每个布局传球被自动执行.但是,在这种情况下,作者选择立即打电话给他们; 这是因为现在需要产生的高度,而不是将来的某个时刻.

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

    结论

    在自定义视图中,请使用以下选项,从最"通用"到"大多数"自定义:

      在视图创建期间创建约束(手动或在IB中)

      如果以后需要更改约束,请覆盖 -updateConstraints.

      如果具有无法通过上述方式描述的复杂布局,则覆盖-layoutSubviews.

    在更改可能使视图约束发生变化的代码中,请调用

    [view setNeedsUpdateConstraints];
    

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

    [view updateConstraintsIfNeeded]; 
    

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

    [view setNeedsLayout]; 
    

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

    [view layoutIfNeeded];
    

    这就是为什么在这种情况下需要所有四个呼叫的原因.

    其他材料

    请查看高级自动布局工具箱文章中的详细说明,objc.io问题#3

    2023-02-13 16:58 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有