layout系列方法的使用区别

layout系列方法的使用区别_第1张图片

我所说的layout系列方法也就是下面的这几个方法:

  • layoutSubviews
  • layoutIfNeeded
  • setNeedsLayout

当然还有一个经常拿来比较的setNeedsDisplay.

layoutSubviews

首先我们先来看看官方是怎么描述的:

layout系列方法的使用区别_第2张图片

在iOS5.1及更早的版本中这个方法默认是不执行的。而在iOS5.1之后,该方法才起作用。
我们可以使用该方法来重新定义子元素的位置和大小,但是我们不能直接调用这个方法,可以重写这个方法来对子视图进行重新布局。如果我们想立即更新布局,需要调用 setNeedsLayout 方法,但该方法不会立即 重绘视图 (drawing)。如果想立即更新视图布局 ,需要调用 layoutIfNeeded方法。

调用时机

官方文档提到了layoutSubviews不是供用户来调用的,而是系统自动调用的,我们能做的就是重写该方法。那么什么时候系统会调用layoutSubviews方法呢?

  • 调用 addSubview 方法时会执行该方法。
  • 设置并改变子视图的frame属性时会触发该方法。
  • 滑动UIScrollView及继承与UIScrollView的控件时会触发该方法。
  • 旋转屏幕时,会触发父视图的layoutSubviews方法。
  • 设置并改变视图的frame属性时会触发父视图的layoutSubviews方法。

setNeedsLayout

Invalidates the current layout of the receiver and triggers a layout update during the next update cycle.

在当前布局周期发送setNeedsLayout消息是无效的,直到下一个布局周期才会触发布局更新。

Call this method on your application’s main thread when you want to adjust the layout of a view’s subviews. This method makes a note of the request and returns immediately. Because this method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated. This behavior allows you to consolidate all of your layout updates to one update cycle, which is usually better for performance.

当你想要调整子视图的布局时,你可以在应用的主线程调用该方法。这个方法将记录布局请求,并立即返回。由于该方法不强制立即更新,而是等到下一个更新周期,所以你可以在当前的无效周期内添加多个视图的布局,等到下一个周期统一更新。这么做通常可以获得更好的性能。

总结:setNeedsLayout标记为需要重新布局,但是不会立即刷新,如果想要立即刷新,需要配合layoutIfNeeded立即更新

layoutIfNeeded

如果,有需要刷新的标记会立即调用layoutSubviews进行布局,如果没有标记,则不会调用layoutSubviews。
如果要立即刷新,要先调用setNeedsLayout方法,把标记设为需要布局,然后马上调用layoutIfNeeded刷新布局

例如下面的小Demo:

@interfaceViewController ()
/** *  距离父控件左边的约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftCos;

/** *  距离父控件顶部的约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topCos;

@end
@implementation ViewController
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 修改约束的值.其实只是执行了setNeedsLayout 标记了需要重新布局,
    //但是没有立即执行。所以我们需要在动画中调用layoutIfNeeded方法立即刷新;
    self.leftCos.constant += 100;   
    self.topCos.constant += 100;  
     
    // 2.执行动画
    [UIView animateWithDuration:5 animations:^{
        // 让view上的约束执行动画
        [self.view layoutIfNeeded];
    }];
}
@end

setNeedsDisplay

layout系列方法的使用区别_第3张图片

setNeedDisplay会在控件上标上一个需要被重新绘图的标记,在下一个绘图周期自动重绘。因为苹果的刷新频率是60hz,也就是1/60秒后重绘

你可能感兴趣的:(layout系列方法的使用区别)