理解setNeedsLayout和layoutIfNeeded的区别

学习文档:https://www.jianshu.com/p/d46bcc656e04 https://www.jianshu.com/p/a84f85729952
概念理解

layoutSubviews:

Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.

这是官方文档,大致意思就是,子类可以根据需要重写此方法,以对其子视图执行更精确的布局。仅当子视图的自动调整大小和基于约束的行为没有提供所需的行为时,才应复写此方法。您可以使用直接设置子视图的框架矩形。我个人理解的就是,平时没事儿不要乱复写,只有在父视图或子视图,bounds改变了,要做出相应的约束更新改变再复写。如果某个视图自身的bounds或者子视图的bounds发生改变,那么这个方法会在当前runloop结束的时候被调用。
为什么不是立即调用呢?因为渲染毕竟比较消耗性能,特别是视图层级复杂的时候。这种机制下任何UI控件布局上的变动不会立即生效,而是每次间隔一个周期,所有UI控件在布局上的变动统一生效并且在视图上更新,苹果通过这种高性能的机制保障了视图渲染的流畅性。

setNeedsLayout:标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,在下一轮runloop结束前刷新,对于这一轮runloop之内的所有布局和UI上的更新只会刷新一次,layoutSubviews一定会被调用。
layoutIfNeeded:如果有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

代码亲测

模拟一个博主的例子我自己试了一下,用mainbord,写一个Button,用来触发改变约束的动作,写一个一开始就给定约束testView

  [self.view layoutIfNeeded];//此方法强制立即布局并显示更新。你可能会想知道为什么在我们进行约束更改之前调用它呢,因为苹果认为这是一个最佳做法,以确保任何以前的更新等待更新周期的完成,所以我已经添加了它
    if ( self.testHeight.constant == 41.00 ) {
        self.testHeight.constant = 80;
    }else {
        self.testHeight.constant = 41;
    }
    
    [UIView animateWithDuration:2.0 animations:^{
        [self.view layoutIfNeeded];//你会发现,是有动画效果的改变约束 
//        [self.view setNeedsLayout];//如果注释掉上一行layoutIfNeeded代码 而把本行放出来,是我动画效果的立即改变约束 
    }completion:^(BOOL finished) {
    }]; 
这是为什么?

在动画里UIView animateWithDuration设置layoutIfNeeded就有动画的改变约束,设置setNeedsLayout没有动画的改变约束?
原因:layoutIfNeeded代表立即刷新,由于约束更改是同步进行的,所以我在约束改变前,和改变中,改变后都会在动画块中展示出来,因此在动画块中捕获来自约束更改的帧移动。而且我亲测,假如没有第一行layoutIfNeeded,现象还是如此,但是我们最好还是按照苹果的建议。
我们再来看一下动画块里注释掉layoutIfNeeded,而调用[self.view setNeedsLayout];
重点来了,那既然setNeedsLayout是下一次刷新才改变,那为什么我会看到约束瞬间改变呢?
这是因为,他本该在下一次runloop结束前刷新,可是我们没有在动画块的上下文进行视图更新,就认为这次周期已经结束了,而块里的代码,又是一个新的周期,因为我们标记为更新,更新周期的发生的地方也是动画开始的地方。没有动画是因为通过setNeedsLayout进行布局更新,所以是在更新周期中立即启动视图更新,而不是从更新周期开始约束更改和帧移动的动画

That‘s all. 以上也算是我中午的一个学习的整理,其实就是把其他优秀的程序员的内容,自己理解翻译了一下。不过不积跬步,何以至千里。当然 日积跬步,也何以至千里啊(捂脸🤦‍♂️)。我们还是要,高效快速学习 笔芯芯~~~~~~~

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容