VC的布局时机、所用方法以及UIView内部布局执行顺序

**这是自己记录知识点,方便忘记的时候回看**

1

这种情况(点击屏幕去添加view),相应的方法打印顺序是如下:

2020-04-15 22:24:34.550917+0800 PrettyRuler[98501:8327173] -[FirstView initWithFrame:]

2020-04-15 22:24:34.552084+0800 PrettyRuler[98501:8327173] -[TwoView initWithFrame:]

2020-04-15 22:24:37.521095+0800 PrettyRuler[98501:8327173] -[ViewController viewWillLayoutSubviews]

2020-04-15 22:24:37.521424+0800 PrettyRuler[98501:8327173] -[TwoView updateConstraints]

2020-04-15 22:24:37.521561+0800 PrettyRuler[98501:8327173] -[FirstView updateConstraints]

2020-04-15 22:24:38.397923+0800 PrettyRuler[98501:8327173] -[ViewController viewDidLayoutSubviews]

2020-04-15 22:24:38.398204+0800 PrettyRuler[98501:8327173] -[FirstView layoutSubviews]

2020-04-15 22:24:38.398318+0800 PrettyRuler[98501:8327173] -[TwoView layoutSubviews]

2020-04-15 22:24:38.398407+0800 PrettyRuler[98501:8327173] -[TwoView layoutSubviews]


2

这种情况(点击屏幕去添加view),相应的方法打印顺序是如下:

2020-04-15 22:34:35.041556+0800 PrettyRuler[98691:8368810] -[FirstView initWithFrame:]

2020-04-15 22:34:35.041960+0800 PrettyRuler[98691:8368810] -[TwoView initWithFrame:]

2020-04-15 22:34:35.042992+0800 PrettyRuler[98691:8368810] -[ViewController viewWillLayoutSubviews]

2020-04-15 22:34:35.043212+0800 PrettyRuler[98691:8368810] -[TwoView updateConstraints]

2020-04-15 22:34:35.043352+0800 PrettyRuler[98691:8368810] -[FirstView updateConstraints]

2020-04-15 22:34:35.043579+0800 PrettyRuler[98691:8368810] -[ViewController viewDidLayoutSubviews]

2020-04-15 22:34:35.043750+0800 PrettyRuler[98691:8368810] -[FirstView layoutSubviews]

2020-04-15 22:34:35.043875+0800 PrettyRuler[98691:8368810] -[TwoView layoutSubviews]

总结:所以1,2这两种情况,不管子控件是以什么方式加到父视图上面去的。(比如1:父视图和子视图都创建好,在把子视图添加到父视图上。2:子视图在父视图的initWithFrame方法里面创建好,在添加上去。) 布局的方法打印的顺序是一样的。

3

这种情况(创建好vc,push到vc,vc第一次显示的时候) 相应的方法打印顺序是如下:

2020-04-15 22:39:37.407416+0800 PrettyRuler[98705:8371830] -[ViewController viewDidLoad]

2020-04-15 22:39:37.407647+0800 PrettyRuler[98705:8371830] -[FirstView initWithFrame:]

2020-04-15 22:39:37.407819+0800 PrettyRuler[98705:8371830] -[TwoView initWithFrame:]

2020-04-15 22:39:37.423148+0800 PrettyRuler[98705:8371830] -[TwoView updateConstraints]

2020-04-15 22:39:37.423283+0800 PrettyRuler[98705:8371830] -[FirstView updateConstraints]

2020-04-15 22:39:37.423594+0800 PrettyRuler[98705:8371830] -[ViewController viewWillLayoutSubviews]

2020-04-15 22:39:37.423912+0800 PrettyRuler[98705:8371830] -[ViewController viewDidLayoutSubviews]

2020-04-15 22:39:37.424054+0800 PrettyRuler[98705:8371830] -[FirstView layoutSubviews]

2020-04-15 22:39:37.424140+0800 PrettyRuler[98705:8371830] -[TwoView layoutSubviews]


4

这种情况(创建好vc,push到vc,vc第一次显示的时候) 相应的方法打印顺序是如下:

2020-04-15 22:46:40.331809+0800 PrettyRuler[98761:8376981] -[ViewController viewDidLoad]

2020-04-15 22:46:40.332063+0800 PrettyRuler[98761:8376981] -[FirstView initWithFrame:]

2020-04-15 22:46:40.333243+0800 PrettyRuler[98761:8376981] -[TwoView initWithFrame:]

2020-04-15 22:46:40.346865+0800 PrettyRuler[98761:8376981] -[TwoView updateConstraints]

2020-04-15 22:46:40.346998+0800 PrettyRuler[98761:8376981] -[FirstView updateConstraints]

2020-04-15 22:46:40.347291+0800 PrettyRuler[98761:8376981] -[ViewController viewWillLayoutSubviews]

2020-04-15 22:46:40.347605+0800 PrettyRuler[98761:8376981] -[ViewController viewDidLayoutSubviews]

2020-04-15 22:46:40.347772+0800 PrettyRuler[98761:8376981] -[FirstView layoutSubviews]

2020-04-15 22:46:40.347863+0800 PrettyRuler[98761:8376981] -[TwoView layoutSubviews]

总结:所以3,4这两种情况,不管子控件是以什么方式加到父视图上面去的。(比如1:父视图和子视图都创建好,在把子视图添加到父视图上。2:子视图在父视图的initWithFrame方法里面创建好,在添加上去。) 布局的方法打印的顺序是一样的。

总的来说1,2的情况和3,4的情况相应的方法打印有些许差别。具体看上面打印信息。

需要注意的地方是:

layoutSubviews的调用顺序都是先调用父视图的,在调用子视图的。不管子视图是单独创建加到父视图上去,还是在父视图的init方法中,创建好,加到父视图上去。都是先调用父视图的layoutSubviews,在调用子视图的layoutSubviews.  

updateConstraints 的调用顺序刚好相反,都是先调用子视图的,在调用父视图的,不管子视图是单独创建加到父视图上去,还是在父视图的init方法中,创建好,加到父视图上去。都是先调用子视图的updateConstraints,在调用父视图的updateConstraints.

layoutSubviews方法都是在viewDidLayoutSubviews方法后面调用。

updateConstraints方法可能在viewWillLayoutSubviews方法之前调用(第一次进vc的时候),也可能是在viewWillLayoutSubviews和viewDidLayoutSubviews之间调用(在vc里面做操作添加view的时候)。不管updateConstraints在哪调用,都是先调用子视图的updateConstraints,在调用父视图的updateConstraints.

用约束布局,只有在控制器的viewDidLayoutSubviews中和控件的layoutSubviews中,才能拿到对应的view或者控件的真实的frame----下面的是实验验证的打印结果

这是刚进vc的时候打印:

各个方法调用期间,view的真实frame,侧面反应了约束生效的周期
2020-04-15 23:09:51.197059+0800 PrettyRuler[98946:8395075] -[ViewController viewDidLoad]

2020-04-15 23:09:51.197312+0800 PrettyRuler[98946:8395075] -[FirstView initWithFrame:]

2020-04-15 23:09:51.198467+0800 PrettyRuler[98946:8395075] -[TwoView initWithFrame:]

2020-04-15 23:09:51.198631+0800 PrettyRuler[98946:8395075] TwoView宽=0.000000---高=0.000000

2020-04-15 23:09:51.200505+0800 PrettyRuler[98946:8395075] FirstView宽=0.000000---高=0.000000

2020-04-15 23:09:51.200655+0800 PrettyRuler[98946:8395075] FirstViewself.view---宽=0.000000---高=0.000000

2020-04-15 23:09:51.202252+0800 PrettyRuler[98946:8395075] viewDidLoad宽=375.000000---高=812.000000

2020-04-15 23:09:51.202997+0800 PrettyRuler[98946:8395075] viewDidLoadself.vieww---宽=0.000000---高=0.000000

2020-04-15 23:09:51.228190+0800 PrettyRuler[98946:8395075] -[TwoView updateConstraints]

2020-04-15 23:09:51.228320+0800 PrettyRuler[98946:8395075] TwoViewupdateConstraints宽=0.000000---高=0.000000

2020-04-15 23:09:51.228804+0800 PrettyRuler[98946:8395075] -[FirstView updateConstraints]

2020-04-15 23:09:51.228911+0800 PrettyRuler[98946:8395075] FirstViewupdateConstraints宽=0.000000---高=0.000000

2020-04-15 23:09:51.229815+0800 PrettyRuler[98946:8395075] FirstViewupdateConstraintssself.view---宽=0.000000---高=0.000000

2020-04-15 23:09:51.230719+0800 PrettyRuler[98946:8395075] -[ViewController viewWillLayoutSubviews]

2020-04-15 23:09:51.236455+0800 PrettyRuler[98946:8395075] viewWillLayoutSubviews宽=375.000000---高=812.000000

2020-04-15 23:09:51.237495+0800 PrettyRuler[98946:8395075] viewWillLayoutSubviewsself.vieww---宽=0.000000---高=0.000000

2020-04-15 23:09:51.239052+0800 PrettyRuler[98946:8395075] -[ViewController viewDidLayoutSubviews]

2020-04-15 23:09:51.239188+0800 PrettyRuler[98946:8395075] viewDidLayoutSubviews宽=375.000000---高=812.000000

2020-04-15 23:09:51.239650+0800 PrettyRuler[98946:8395075] viewDidLayoutSubviewsself.vieww---宽=200.000000---高=200.000000

2020-04-15 23:09:51.239981+0800 PrettyRuler[98946:8395075] -[FirstView layoutSubviews]

2020-04-15 23:09:51.240066+0800 PrettyRuler[98946:8395075] FirstViewlayoutSubviews宽=200.000000---高=200.000000

2020-04-15 23:09:51.240152+0800 PrettyRuler[98946:8395075] FirstViewlayoutSubviewsself.view---宽=100.000000---高=100.000000

2020-04-15 23:09:51.241178+0800 PrettyRuler[98946:8395075] -[TwoView layoutSubviews]

2020-04-15 23:09:51.241723+0800 PrettyRuler[98946:8395075] TwoViewlayoutSubviews宽=100.000000---高=100.000000

这是在vc里面做操作添加view的时候打印:
2020-04-15 23:21:51.724187+0800 PrettyRuler[98999:8402150] -[FirstView initWithFrame:]

2020-04-15 23:21:51.724749+0800 PrettyRuler[98999:8402150] -[TwoView initWithFrame:]

2020-04-15 23:21:51.725170+0800 PrettyRuler[98999:8402150] TwoView宽=0.000000---高=0.000000

2020-04-15 23:21:51.726307+0800 PrettyRuler[98999:8402150] FirstView宽=0.000000---高=0.000000

2020-04-15 23:21:51.726464+0800 PrettyRuler[98999:8402150] FirstViewself.view---宽=0.000000---高=0.000000

2020-04-15 23:21:51.727286+0800 PrettyRuler[98999:8402150] -[ViewController viewWillLayoutSubviews]

2020-04-15 23:21:51.727608+0800 PrettyRuler[98999:8402150] viewWillLayoutSubviews宽=375.000000---高=812.000000

2020-04-15 23:21:51.728268+0800 PrettyRuler[98999:8402150] viewWillLayoutSubviewsself.vieww---宽=0.000000---高=0.000000

2020-04-15 23:21:51.728945+0800 PrettyRuler[98999:8402150] -[TwoView updateConstraints]

2020-04-15 23:21:51.729609+0800 PrettyRuler[98999:8402150] TwoViewupdateConstraints宽=0.000000---高=0.000000

2020-04-15 23:21:51.731981+0800 PrettyRuler[98999:8402150] -[FirstView updateConstraints]

2020-04-15 23:21:51.732757+0800 PrettyRuler[98999:8402150] FirstViewupdateConstraints宽=0.000000---高=0.000000

2020-04-15 23:21:51.733231+0800 PrettyRuler[98999:8402150] FirstViewupdateConstraintssself.view---宽=0.000000---高=0.000000

2020-04-15 23:21:51.733803+0800 PrettyRuler[98999:8402150] -[ViewController viewDidLayoutSubviews]

2020-04-15 23:21:51.734468+0800 PrettyRuler[98999:8402150] viewDidLayoutSubviews宽=375.000000---高=812.000000

2020-04-15 23:21:51.734944+0800 PrettyRuler[98999:8402150] viewDidLayoutSubviewsself.vieww---宽=300.000000---高=300.000000

2020-04-15 23:21:51.745458+0800 PrettyRuler[98999:8402150] -[FirstView layoutSubviews]

2020-04-15 23:21:51.745805+0800 PrettyRuler[98999:8402150] FirstViewlayoutSubviews宽=300.000000---高=300.000000

2020-04-15 23:21:51.745893+0800 PrettyRuler[98999:8402150] FirstViewlayoutSubviewsself.view---宽=250.000000---高=250.000000

2020-04-15 23:21:51.746002+0800 PrettyRuler[98999:8402150] -[TwoView layoutSubviews]

2020-04-15 23:21:51.746090+0800 PrettyRuler[98999:8402150] TwoViewlayoutSubviews宽=250.000000---高=250.000000

补充:

有时候出现列表(UITableView,UICollectionView)底部显示不完全的情况,是因为列表的frame高度大于当前父视图的frame高度.

这种情况出现,跟用frame布局还是masonry布局没有关系,跟列表的contentSize也没有关系。只能列表的frame高度和父视图frame的高度有关系,当列表的frame高度大于父视图的frame高度的时候,就会出现列表底部显示不完全的情况

第一次进来:

2020-04-16 12:10:27.458593+0800 PrettyRuler[17228:8718129] viewWillLayoutSubviews----view{{0, 0}, {375, 812}}----tableView{{0, 0}, {0, 0}}

2020-04-16 12:10:27.461366+0800 PrettyRuler[17228:8718129] viewDidLayoutSubviews----view{{0, 0}, {375, 812}}----tableView{{0, 0}, {375, 812}}

此时列表能显示完全

第一旋转屏幕

2020-04-16 12:11:15.666189+0800 PrettyRuler[17228:8718129] viewWillLayoutSubviews----view{{0, 0}, {812, 375}}----tableView{{0, 0}, {375, 812}}

2020-04-16 12:11:15.671216+0800 PrettyRuler[17228:8718129] viewDidLayoutSubviews----view{{0, 0}, {812, 375}}----tableView{{0, 0}, {812, 375}}

此时列表能显示完全

点击修改列表的约束

2020-04-16 12:11:40.317089+0800 PrettyRuler[17228:8718129] viewWillLayoutSubviews----view{{0, 0}, {812, 375}}----tableView{{0, 0}, {812, 375}}

2020-04-16 12:11:40.317585+0800 PrettyRuler[17228:8718129] viewDidLayoutSubviews----view{{0, 0}, {812, 375}}----tableView{{0, 0}, {812, 450}}

此时列表底部显示不完全,因为列表frame的高度大于列表父视图frame的高度

恢复旋转了的屏幕

2020-04-16 12:12:14.781476+0800 PrettyRuler[17228:8718129] viewWillLayoutSubviews----view{{0, 0}, {375, 812}}----tableView{{0, 0}, {812, 450}}

2020-04-16 12:12:14.787619+0800 PrettyRuler[17228:8718129] viewDidLayoutSubviews----view{{0, 0}, {375, 812}}----tableView{{0, 0}, {375, 450}}

此时列表能显示完全

此时相关布局方法的打印顺序为:

2020-04-16 21:08:30.915538+0800 PrettyRuler[27731:8977413] -[ViewController viewDidLoad]

2020-04-16 21:08:30.915811+0800 PrettyRuler[27731:8977413] -[TestView initWithFrame:]

2020-04-16 21:08:30.915933+0800 PrettyRuler[27731:8977413] initWithFrame--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:08:30.917328+0800 PrettyRuler[27731:8977413] viewDidLoad--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:08:30.930812+0800 PrettyRuler[27731:8977413] -[TestView updateConstraints]

2020-04-16 21:08:30.930949+0800 PrettyRuler[27731:8977413] updateConstraints--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:08:30.931251+0800 PrettyRuler[27731:8977413] -[ViewController viewWillLayoutSubviews]

2020-04-16 21:08:30.931350+0800 PrettyRuler[27731:8977413] viewWillLayoutSubviews--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:08:30.931638+0800 PrettyRuler[27731:8977413] -[ViewController viewDidLayoutSubviews]

2020-04-16 21:08:30.931731+0800 PrettyRuler[27731:8977413] viewDidLayoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

2020-04-16 21:08:30.931824+0800 PrettyRuler[27731:8977413] -[TestView layoutSubviews]

2020-04-16 21:08:30.931903+0800 PrettyRuler[27731:8977413] layoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

此时相关布局方法的打印顺序为:
2020-04-16 21:13:52.619687+0800 PrettyRuler[27768:8981548] -[ViewController viewDidLoad]

2020-04-16 21:13:52.619987+0800 PrettyRuler[27768:8981548] -[TestView initWithFrame:]

2020-04-16 21:13:52.620109+0800 PrettyRuler[27768:8981548] initWithFrame--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:13:52.621633+0800 PrettyRuler[27768:8981548] -[TestView updateConstraints]

2020-04-16 21:13:52.621765+0800 PrettyRuler[27768:8981548] updateConstraints--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:13:52.622102+0800 PrettyRuler[27768:8981548] -[TestView layoutSubviews]

2020-04-16 21:13:52.622568+0800 PrettyRuler[27768:8981548] layoutSubviews--testViewFrame{{-100, -100}, {200, 200}}

2020-04-16 21:13:52.622692+0800 PrettyRuler[27768:8981548] viewDidLoad--testViewFrame{{-100, -100}, {200, 200}}

2020-04-16 21:13:52.636462+0800 PrettyRuler[27768:8981548] -[ViewController viewWillLayoutSubviews]

2020-04-16 21:13:52.636595+0800 PrettyRuler[27768:8981548] viewWillLayoutSubviews--testViewFrame{{-100, -100}, {200, 200}}

2020-04-16 21:13:52.636893+0800 PrettyRuler[27768:8981548] -[ViewController viewDidLayoutSubviews]

2020-04-16 21:13:52.637000+0800 PrettyRuler[27768:8981548] viewDidLayoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

此时相关布局方法的打印顺序为:
2020-04-16 21:18:15.733870+0800 PrettyRuler[27789:8984633] -[ViewController viewDidLoad]

2020-04-16 21:18:15.734137+0800 PrettyRuler[27789:8984633] -[TestView initWithFrame:]

2020-04-16 21:18:15.734262+0800 PrettyRuler[27789:8984633] initWithFrame--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:18:15.735779+0800 PrettyRuler[27789:8984633] -[TestView updateConstraints]

2020-04-16 21:18:15.736018+0800 PrettyRuler[27789:8984633] updateConstraints--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:18:15.736692+0800 PrettyRuler[27789:8984633] -[ViewController viewWillLayoutSubviews]

2020-04-16 21:18:15.736872+0800 PrettyRuler[27789:8984633] viewWillLayoutSubviews--testViewFrame{{0, 0}, {0, 0}}

2020-04-16 21:18:15.737154+0800 PrettyRuler[27789:8984633] -[ViewController viewDidLayoutSubviews]

2020-04-16 21:18:15.737418+0800 PrettyRuler[27789:8984633] viewDidLayoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

2020-04-16 21:18:15.737536+0800 PrettyRuler[27789:8984633] -[TestView layoutSubviews]

2020-04-16 21:18:15.737622+0800 PrettyRuler[27789:8984633] layoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

2020-04-16 21:18:15.737715+0800 PrettyRuler[27789:8984633] viewDidLoad--testViewFrame{{87.666666666666686, 306}, {200, 200}}

2020-04-16 21:18:15.754966+0800 PrettyRuler[27789:8984633] -[ViewController viewWillLayoutSubviews]

2020-04-16 21:18:15.755112+0800 PrettyRuler[27789:8984633] viewWillLayoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

2020-04-16 21:18:15.755333+0800 PrettyRuler[27789:8984633] -[ViewController viewDidLayoutSubviews]

2020-04-16 21:18:15.755457+0800 PrettyRuler[27789:8984633] viewDidLayoutSubviews--testViewFrame{{87.666666666666686, 306}, {200, 200}}

通过打印发现:在添加完约束的代码后面,立即调用父视图的layoutIfNeeded,会获取子视图的真实的x值,y值,宽和高。 如果子视图自己调用layoutIfNeeded,只会获取到自己真实的宽和高,获取不到真实的自己真实的x值,y值。

你可能感兴趣的:(VC的布局时机、所用方法以及UIView内部布局执行顺序)