所有这些自动布局更新方法有什么区别?都是必须的吗? [英] What is the difference between all these Auto Layout update methods? Are all necessary?

查看:16
本文介绍了所有这些自动布局更新方法有什么区别?都是必须的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,调用了这四个方法进行布局推理.不过,我有点困惑为什么需要所有这些,以及它们彼此之间的不同之处.它们用于通过自动布局使单元格的高度动态化.(取自 这个存储库 来自 这个问题.)

In the code below, these four methods are called for layout reasoning. I'm a little confused why all of them are needed, though, and what they do differently from one another. They're used in the process to make a cell's height be dynamic with Auto Layout. (Taken from this repository from this question.)

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

它来自这个单元格高度的代码块:

And it's from this block of code for the cell's height:

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

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

But what are they doing differently? Why are they all needed?

推荐答案

Layout

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

Layout

Suppose you encapsulate your view logic in a UIView subclass, and call it SomeView. This means that SomeView should know how to layout itself, that is, how to position some other views inside it (you can also create a view that draws itself without using any subviews, but that's beyond the needs of an average developer).

此布局由[SomeView layoutSubviews] 完成.您可以选择覆盖它:

This layout is done by [SomeView layoutSubviews]. You have an option of overriding it:

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

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

but you rarely need to do so. In the dark ages of Cocoa Touch, this manual layout was widespread, but now I'd say 99% of layouts can be covered with Auto Layout.

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

The system needs to know when it should call [UIView layoutSubviews]. It's obviously done the first time you need to draw a view, but it may be also called whenever the superview frame changes. Here's a detailed explanation.

所以系统经常调用[view layoutIfNeeded].也可以在任何时候调用它,但只有当有一些事件调用了[view setNeedsLayout]或者你手动调用它时才会有效果,就像在这种情况下一样.

So the system often calls [view layoutIfNeeded]. You can also call it at any time, but this will have an effect only if there is some event that has called [view setNeedsLayout] or if you have called it manually, as in this case.

自动布局(在 文档) 被这样调用是因为您将 [SomeView layoutSubviews] 保留为它继承自 UIView 和用约束来描述你的子视图的位置.

The Auto Layout (capitalized this way in the documentation) is called like that because you're leaving [SomeView layoutSubviews] as it is inherited from UIView and describe the position of your subviews instead in terms of constraints.

使用自动布局时,系统将在每次布局传递时调用[view updateConstraintsIfNeeded].但是,仅当设置了标志 [view setNeedsUpdateConstraints]; 时,该方法才会调用 -updateConstraints(真正起作用).

When using Auto Layout, system will perform calls to [view updateConstraintsIfNeeded] at each layout pass. However, only if the flag [view setNeedsUpdateConstraints]; is set, the method calls into -updateConstraints (which does the real job).

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

If you don't use Auto Layout, those methods are not relevant.

您可以像在本例中那样实现它.

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

It's rarely necessary to call -layoutIfNeeded and -updateConstraintsIfNeeded directly, because UI engine will do that automatically at each layout pass. However, in this case the author has chosen to call them immediately; this is because the resulting height is needed right now, not at some point in the future.

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

This method of updating the cell's height seems right. Note that cell could be a newly created cell and thus not added into view hierarchy yet; this does not impact its ability to layout itself.

在您的自定义视图中使用以下选项,从最通用"到最自定义":

In your custom view go with the following options, starting from the most 'universal' to most 'customized':

  1. 在视图创建过程中创建约束(手动或在 IB 中)
  2. 如果您稍后需要更改约束,请覆盖 -updateConstraints.
  3. 如果有无法通过上述方式描述的复杂布局,请覆盖 -layoutSubviews.

在更改某些内容可能使您的视图的约束发生变化的代码中,调用

In the code that changes something that could make your view's constraints change, call

[view setNeedsUpdateConstraints];

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

If you need results immediately, call also

[view updateConstraintsIfNeeded]; 

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

If the code changes view's frame use

[view setNeedsLayout]; 

最后,如果您想要立即获得结果,请致电

and finally if you want the results immediately, call

[view layoutIfNeeded];

这就是为什么在这种情况下需要所有四个调用.

This is why all four calls are required in this case.

看文章中的详细解释高级自动布局工具箱objc.io issue #3

Take a look at detailed explanation in the article Advanced Auto Layout Toolbox, objc.io issue #3

这篇关于所有这些自动布局更新方法有什么区别?都是必须的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆