iOS layoutSubviews 和 layoutIfNeeded

[引用]https://juejin.cn/post/7435302945408679977

layoutSubviews的调用时机(下面的布局都是通过autolayout、Masonry布局)

  1. init初始化不会触发layoutSubviews,使用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发。
  2. addSubview会触发layoutSubviews。
   AView * aView = [[AView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    [self.view addSubview:aView];
  1. 通过Masonry更新也会调用 但是如果你是在addSubview之后立即设置了约束,那么AView的layoutSubviews只会调用两次并且打印的是最新的frame,这个应该和runloop有关可以看上面的链接https://juejin.cn/post/743530294540867997
    如果是延迟加载并且修改了size则会调用layoutSubviews
AView * aView = [[AView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    [self.view addSubview:aView];
    [aView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.leading.offset(0);
        make.width.height.offset(200);
    }];
AView-[AView layoutSubviews]--frame={{0, 0}, {200, 200}}
AView-[AView layoutSubviews]--frame={{0, 0}, {200, 200}}
-----
 AView * aView = [[AView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    [self.view addSubview:aView];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [aView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.leading.offset(0);
            make.width.height.offset(200);
        }];
        
    });
AView-[AView layoutSubviews]--frame={{0, 0}, {100, 100}}
AView-[AView layoutSubviews]--frame={{0, 0}, {100, 100}}
AView-[AView layoutSubviews]--frame={{0, 0}, {200, 200}}
  1. 手动调用setNeedsLayout: 如果我们手动调用了视图的setNeedsLayout方法,系统将会在下一个绘制周期调用layoutSubviews。
  2. 父视图的size发生了改变,那么父视图的layoutSubviews和子视图的layoutSubviews都会被调用(前提是使用autolayout布局),但是在父视图A的layoutSubviews里面 拿到的子视图B的frame是原来的frame,所以如果想拿到子视图B最新的frame,需要调用子视图B的 layoutIfNeeded
  3. 子视图B的size发生变化会触发A和B的layoutSubviews,但是如果只是修改了origin,那么只会出发B的layoutSubviews
  4. 如果采用的是frame来布局的话,改变A的size只会触发A的layoutSubviews
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容