现在代码中已经创建了两个NSLayoutConstraint对象数组,下面需要将它们添加到某个视图中。UIView有一个可以同时添加多个约束的实例方法:
- (void)addConstraints:(NSArray *)constraints
那么,如何判断约束应该添加到哪个视图中呢?以下是判定法则:
•如果约束同时对多个父视图相同的视图起作用(例如图16-1中的约束“A”),那么约束应该添加到它们的父视图中。
•如果约束只对某个视图自身起作用(例如约束“B”),那么约束应该添加到该视图中。
•如果约束同时对多个父视图不同的视图起作用(例如图16-1中的约束“C”),但是这些视图在层次结构中有共同的祖先视图,那么约束应该添加到它们最近一级的祖先视图中。
•如果约束同时对某个视图及其父视图起作用(例如约束“D”),那么约束应该添加到其父视图中。
图16-1 视图层次结构与约束之间的关系
在imageView的水平方向上,约束同时对imageView及其父视图起作用,因此约束应该添加到imageView的父视图——BNRDetailViewController的view中。
而在垂直方向上,约束同时对imageView、dateLabel和toolbar起作用,这三个视图的父视图都是BNRDetailViewController的view,因此约束应添加到它们的父视图中。
在BNRDetailViewController.m中修改viewDidLoad方法,将两个NSLayout- Constraint对象数组添加到BNRDetailViewController的view中,代码如下:
…
NSArray *verticalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:
@“V:[dateLabel]-[imageView]-[toolbar]”
options:0
metrics:nil
views:nameMap];
[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
}
构建并运行应用。创建一个BNRItem对象,然后为其设置一张图片。这时,根据所设置的图片大小,详细界面看起来可能正常,也可能有问题。如果图片比较小,那么详细界面可能类似于图16-2。
图16-2 选择小尺寸图片导致的布局问题
为了理解这种情况发生的原因,首先要介绍固有内容大小(intrinsic content size)的概念。
(请注意,目前自动布局系统存在一个bug,可能导致valueField的约束出现问题。对于基准线约束,如之前添加的使valueField与valueLabel沿基准线对齐,有时并不起作用。如果读者的valueField有问题,请删除其基准线约束,然后添加一个垂直方向的约束。)