[引用]https://juejin.cn/post/7435302945408679977
layoutSubviews的調(diào)用時(shí)機(jī)(下面的布局都是通過autolayout、Masonry布局)
- init初始化不會(huì)觸發(fā)layoutSubviews,使用initWithFrame 進(jìn)行初始化時(shí),當(dāng)rect的值不為CGRectZero時(shí),也會(huì)觸發(fā)。
- addSubview會(huì)觸發(fā)layoutSubviews。
AView * aView = [[AView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
[self.view addSubview:aView];
- 通過Masonry更新也會(huì)調(diào)用 但是如果你是在addSubview之后立即設(shè)置了約束,那么AView的layoutSubviews只會(huì)調(diào)用兩次并且打印的是最新的frame,這個(gè)應(yīng)該和runloop有關(guān)可以看上面的鏈接https://juejin.cn/post/743530294540867997
如果是延遲加載并且修改了size則會(huì)調(diào)用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}}
- 手動(dòng)調(diào)用setNeedsLayout: 如果我們手動(dòng)調(diào)用了視圖的setNeedsLayout方法,系統(tǒng)將會(huì)在下一個(gè)繪制周期調(diào)用layoutSubviews。
- 父視圖的size發(fā)生了改變,那么父視圖的layoutSubviews和子視圖的layoutSubviews都會(huì)被調(diào)用(前提是使用autolayout布局),但是在父視圖A的layoutSubviews里面 拿到的子視圖B的frame是原來(lái)的frame,所以如果想拿到子視圖B最新的frame,需要調(diào)用子視圖B的
layoutIfNeeded - 子視圖B的size發(fā)生變化會(huì)觸發(fā)A和B的layoutSubviews,但是如果只是修改了origin,那么只會(huì)出發(fā)B的layoutSubviews
- 如果采用的是frame來(lái)布局的話,改變A的size只會(huì)觸發(fā)A的layoutSubviews