其间有几个为主的布局方法要求精晓,平日不知所厝而扬弃了运用 Autolayout

UIView是咱们平时利用的几个着力控件,当中有多少个为主的布局方法供给驾驭。

刚最初接纳 Autolayout
境遇上边包车型地铁警告人轻易令人颓丧,日常不知所厝而丢掉了应用 Autolayout。

  • layoutSubViews:
    增多子视图常重写那个办法,那些办法是用来再度布局子视图的,常用来对子视图布局,或然在其余格局中调用以到达重新布局的职能。

  • setNeedsLayout
    告知页面须要更新,不过不会马上初叶更新,施行后会马上调用layoutSubviews

  • layoutIfNeeded
    报告页面布局即刻更新,所以一般都会和setNeedsLayout一路使用。若是期望马上生成新的frame内需调用此方式,利用那一点一般布局动画能够在立异布局后平素动用那几个措施让动画片生效。

  • setNeedsUpdateConstraints
    报告需求立异约束,不过不会立时起先

  • updateConstraintsIfNeeded
    报告立时更新约束

  • updateConstraints
    系统立异约束

Unable to simultaneously satisfy constraints.Probably at least one of the constraints in the following list is one you don't want.Try this: look at each constraint and try to figure out which you don't expect; find the code that added the unwanted constraint or constraints and fix it.(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)(...........)Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

触发layoutSubviews的时机

  • init措施早先化不会触发layoutSubviews,可是是用initWithFrame
    进行开始化时,当rect的值不为CGRectZero时,会触发。
  • addSubview方法会触发layoutSubviews
  • 设置viewFrame会触发layoutSubviews,前提是frame的值设置内外产生了变动。
  • 滚动一个UIScrollView会触发layoutSubviews
  • 旋转Screen会触发父UIView上的layoutSubviews
  • 改动三个UIView大小的时候也会触发父UIView上的layoutSubviews

留神:layoutSubViews在drawRect在此之前调用。

正如输出中所述,Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger,未来牵线下行使
UIViewAlertForUnsatisfiableConstraints 的调和方法。

UIViewAlertForUnsatisfiableConstraints 添加 symbolic breakpoint

  • 展开断点导航
  • 点击左下角的+开关
  • 选择Add Symbolic Breakpoint
  • 在Symbol添加UIViewAlertForUnsatisfiableConstraints

图片 1image.png

重复调节和测量检验的时候就可以透过 lldb 来调解了,然并卵,要是您不掌握 lldb 的话。

之所以交给你八个小本领,增多

po [[UIWindow keyWindow] _autolayoutTrace] // OC项目expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace] // Swift项目

图片 2image.png

与此相类似就能够一直看出输出:

 po [[UIWindow keyWindow] _autolayoutTrace]UIWindow:0x7f9481c93360| •UIView:0x7f9481c9d680| | *UIView:0x7f9481c9d990- AMBIGUOUS LAYOUT for UIView:0x7f9481c9d990.minX{id: 13}, UIView:0x7f9481c9d990.minY{id: 16}| | *_UILayoutGuide:0x7f9481c9e160- AMBIGUOUS LAYOUT for _UILayoutGuide:0x7f9481c9e160.minY{id: 17}| | *_UILayoutGuide:0x7f9481c9ebb0- AMBIGUOUS LAYOUT for _UILayoutGuide:0x7f9481c9ebb0.minY{id: 27}

内部 AMBIGUOUS
相关的视图就是封锁有题指标。0x7f9481c9d990正是不正常视图的首地址。

当然更是的调治将养必要 lldb 的通令。举个例子,打字与印刷视图对象

 po 0x7f9481c9d990<UIView: 0x7f9481c9d990; frame = (0 0; 768 359); autoresize = RM+BM; layer = <CALayer: 0x7fc82d338960>>

改变颜色:

 expr (0x174197010).backgroundColor = [UIColor redColor](UICachedDeviceRGBColor *) $4 = 0x0000000174469cc0

剩下的正是去代码中找到那些视图,然后修改其约束了。

UIView 是我们平时使用的三个主导控件,个中有多少个为主的布局方法要求理解。

  • layoutSubViews:

View 及其怀有子视图的 frame 爆发变动的时候,会调用
layoutSubviews,所以在供给更新 frame
来再度定位或转移大小时重载它。这一个情势很开支非常大,因为它会在各样子视图上起功效同一时候调用它们相应的
layoutSubviews 方法。注意:Infiniti不用在代码中手动调用 layoutSubviews
方法
。当 layoutSubviews 完成后,在 view 的全数者 view controller
上,会触发 viewDidLayoutSubviews 调用。因为 viewDidLayoutSubviews
view
布局更新后会被独一可信调用的办法,所以你应有把具有正视于布局照旧大小的代码放在
viewDidLayoutSubviews 中,而不是放在 viewDidLoad 或者
viewDidAppear 中。

触发 layoutSubviews 的时机:

  • addSubview 方法会触发 layoutSubviews

  • viewFrame 产生变化也会触发layoutSubviews

  • 滚动贰个 UIScrollView 会触发 layoutSubviews

  • 旋转荧屏会触发父 View 上的 layoutSubviews

  • 改换三个 View 大小的时候也会触发父 View 上的 layoutSubviews

  • setNeedsLayout触发 layoutSubviews
    调用的最省能源的艺术就是在你的视图上调用 setNeedsLaylout
    方法,表示视图的布局必要再度总结。告知页面供给立异,但是不会登时初始更新视图,视图会在下二个
    runloop 中更新,调用 setNeedsLaylout
    方法视图被再一次绘制并布局里面会有一段任性时间的间距。

  • layoutIfNeeded调用 layoutIfNeeded 会触发
    layoutSubviews,告知页面布局即刻更新,所以一般都会和
    setNeedsLayout 一同使用。如若期待即刻生成新的 frame
    须要调用此方法,利用这一点一般布局动画能够在立异布局后一直动用那个办法让动画片生效。

  • setNeedsUpdateConstraints告知要求立异约束,可是不会应声开端,在下一遍
    runloop 中更新约束,通过标志 update constraints 来触发
    updateConstraints

  • updateConstraintsIfNeeded告知马上更新约束,那一个主意与
    layoutIfNeeded 等价。它会检查 update constraints
    标志。若是以为那么些约束供给被更新,它会立刻触发
    updateConstraints,而不会等到 run loop 的末尾。

  • updateConstraints系统立异约束,注意:最为不用在代码中手动调用
    updateConstraints 方法
    。通常在 updateConstraints
    方法中落实必供给创新的羁绊,在设置恐怕免除约束、退换约束的优先级也许常量值,可能从视图层级中移除三个视图时都会设置一个之中的标识
    update constarints,这一个标志会在下四个立异周期中触发调用
    updateConstrains

留意:layoutSubViews 在 drawRect 以前调用。

在应用 AutoLayout 的时候大概也会同时也会用到 frame,比如必要用到 layer
的时候,想让 layer
的尺寸是由其余视图尺寸设定的,而这么些视图又是由约束调控布局的,即便将
layer 的早先化与 view 的起始化放在贰个主意中;举个例子:

layer.bounds = CGRectMake(0,0,view.bounds.size.widith * 0.5,50)

那便是说异常的大概获得 layer 的幅度是0。

比如:

UIView *redView = [[UIView alloc] init];redView.backgroundColor = [UIColor redColor];[self.view addSubview:redView];self.redView = redView; // 设置约束[redView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view.mas_centerX); make.centerY.equalTo(self.view.mas_centerY); make.size.mas_equalTo(CGSizeMake;}]; NSLog(@"self.view 的尺寸%@,redView 的尺寸%@",self.view,redView);2017-06-08 15:32:51.815107+0800 MasonryDemo[42940:1076244] self.view 的尺寸<UIView: 0x7fd8cd408960; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x604000227200>>,redView 的尺寸<UIView: 0x7fd8cd407650; frame = ; layer = <CALayer: 0x6040002274a0>>

以此时候,看到为何设置了自律,而打字与印刷出来的 frame 是
,是因为约束被安装之后它并不会霎时对 view 作出变动,而是要等到 layout
时,才会对视图的尺码举办退换,而 layout
平日是在视图已经加载到父视图上面时做出响应。

进而如若在 viewDidLoad 中设置了束缚,那么要等到 viewDidAppear 时 view
的尺寸才会真正转移。

消除办法:

- testLayout { UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; self.redView = redView; // 设置约束 [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view.mas_centerX); make.centerY.equalTo(self.view.mas_centerY); make.size.mas_equalTo(CGSizeMake; }];}- viewDidLayoutSubviews { [super viewDidLayoutSubviews]; NSLog(@"self.view 的尺寸%@,redView 的尺寸%@",self.view,self.redView);}2017-06-08 15:50:41.621147+0800 MasonryDemo[43363:1089098] self.view 的尺寸<UIView: 0x7fe412f0f780; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x604000238b00>>,redView 的尺寸<UIView: 0x7fe412e045b0; frame = (132 328; 150 80); layer = <CALayer: 0x60000003c460>>

1、把得到 frame 的设置写到 layoutSubviews 中也许写到
viewDidLayoutSubviews 中就能够。因为 layout 约束生效时 view 的 center 可能bounds 就能够被修改,当 center 大概 bounds 被改造时layoutSubview
就能够被调用,随后 viewDidLayoutSubviews
就回被调用。那一年,设置约束的视图 frame 就不再是 了。

- testLayout { UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; self.redView = redView; // 设置约束 [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view.mas_centerX); make.centerY.equalTo(self.view.mas_centerY); make.size.mas_equalTo(CGSizeMake; }]; [redView setNeedsLayout]; [redView layoutIfNeeded]; NSLog(@"self.view 的尺寸%@,redView 的尺寸%@",self.view,redView);}2017-06-08 15:52:32.749105+0800 MasonryDemo[43419:1090641] self.view 的尺寸<UIView: 0x7fe36440b5f0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x604000422100>>,redView 的尺寸<UIView: 0x7fe364405040; frame = (-75 -40; 150 80); layer = <CALayer: 0x6040004207a0>>

2、假如将封锁和 frame 写在平等方法中,写完约束就安装 frame,并不是想把
frame 的设存放到 layoutSubview
中,例如设置好约束后当即就想依赖约束的结果计算高度,那么必得在设置完约束之后手动调用setNeedsLayout
和 layoutIfNeeded 方法,让视图马上 layout,更新
frame,但是那年就能够获得实在的 size 并不可能获得真正的 center
,不提议如此使用

- testLayout { UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; self.redView = redView; // 设置约束 [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view.mas_centerX); make.centerY.equalTo(self.view.mas_centerY); make.size.mas_equalTo(CGSizeMake; }]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"self.view 的尺寸%@,redView 的尺寸%@",self.view,redView); });}2017-06-08 15:55:56.282546+0800 MasonryDemo[43500:1092911] self.view 的尺寸<UIView: 0x7fda85e0d540; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x600000233620>>,redView 的尺寸<UIView: 0x7fda85e0c770; frame = (132 328; 150 80); layer = <CALayer: 0x600000233540>>

3、在 dispatch_after 里面能够获得真正的 frame
,或然是因为安装约束和获得 frame 不在同三个 runloop 的由来吗。

相关文章

网站地图xml地图