首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》16.6 深入学习:NSAutoresizingMaskLayoutConstraint

关灯直达底部

在Apple引入自动布局系统之前,iOS应用一直使用自动缩放掩码管理视图布局,视图只具有相对于父视图的自动缩放掩码,无法设置与兄弟视图之间的布局关系。

默认情况下,视图会将自动缩放掩码转换为对应的约束,这类约束经常会与手动添加的约束产生冲突,下面就演示这类冲突。

在viewDidLoad中,注释掉禁用转换自动缩放掩码的代码:

// 设置UIImageView对象的内容缩放模式

iv.contentMode = UIViewContentModeScaleAspectFit;

// 告诉自动布局系统不要将自动缩放掩码转换为约束

// iv.translatesAutoresizingMaskIntoConstraints = NO;

// 将UIImageView对象添加到view上

[self.view addSubview:iv];

现在UIImageView对象会将自动缩放掩码转换为约束。构建并运行应用,然后进入详细界面。这时控制台会输出布局问题和解决建议。

Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't

want. Try this: (1) look at each constraint and try to figure out which you don't

expect; (2) 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)

“”,

“<NSLayoutConstraint:0x9153ee0

H:|-(20)-[UILabel:0x9149f00] (Names: '|':UIControl:0x91496e0 )>”,

“<NSLayoutConstraint:0x9153fa0

UILabel:0x9149970.leading == UILabel:0x9149f00.leading>”,

“<NSLayoutConstraint:0x91540c0

UILabel:0x914a1e0.leading == UILabel:0x9149970.leading>”,

“<NSLayoutConstraint:0x9154420

H:[UITextField:0x914fe20]-(20)-|

(Names: '|':UIControl:0x91496e0 )>”,

“<NSLayoutConstraint:0x9154450

H:[UILabel:0x914a1e0]-(12)-[UITextField:0x914fe20]>”,

“<NSLayoutConstraint:0x912f5a0 (Names: '|':UIControl:0x91496e0 )>”,

H:|-(NSSpace(20))-[UIImageView:0x91524d0

“<NSLayoutConstraint:0x91452a0 (Names: '|':UIControl:0x91496e0 )>”,

H:[UIImageView:0x91524d0]-(NSSpace(20))-|

“<NSAutoresizingMaskLayoutConstraint:0x905f130

h=--& v=--& UIImageView:0x91524d0.midX ==>”

Will attempt to recover by breaking constraint

<NSLayoutConstraint:0x914a2e0 H:[UILabel:0x914a1e0(42)]>

第15章介绍过,以上输出表明多个约束之间发生了冲突,Xcode无法同时满足所有约束。其中,与问题相关的所有约束都会以固定格式依次列举出来,例如,

<NSLayoutConstraint:0x9153fa0

UILabel:0x9149970.leading == UILabel:0x9149f00.leading>

以上格式首先是约束对象的类名和内存地址,然后是约束的作用,在本例中,位于0x9153fa0的约束限定0x9153fa0和0x9149970两个UILabel对象左对齐。

可以注意到,按照以上格式,除最后一个约束外,其余约束的类名都是NSLayoutConstraint。最后一个约束是由UIImageView对象的自动缩放掩码转换而来的,所以类名是NSAutoresizingMaskLayoutConstraint。

最后是Xcode所忽略的约束。可以看到,Xcode忽略的是之前手动为UILabel对象添加的宽度约束,而不是NSAutoresizingMaskLayoutConstraint对象,所以导致界面布局与期望不同。

现在读者可以理解设置translatesAutoresizingMaskIntoConstraints属性为NO的原因了,其作用就是避免自动布局系统生成与其他约束产生冲突的NSAutoresizingMask- LayoutConstraint对象。

最后请读者恢复viewDidLoad中的代码:

// 设置UIImageView对象的内容缩放模式

iv.contentMode = UIViewContentModeScaleAspectFit;

// 告诉自动布局系统不要将自动缩放掩码转换为约束

iv.translatesAutoresizingMaskIntoConstraints = NO;

// 将UIImageView对象添加到view上

[self.view addSubview:iv];