在代码中,约束是NSLayoutConstraint类的对象,添加约束时,需要先创建NSLayoutConstraint对象,再将其添加到视图对象中。在XIB文件中创建并添加约束只需要一步就可以完成,但是在代码中,创建和添加约束需要分为两个不同的步骤。
NSLayoutConstraint提供了一个类方法,可以根据视觉化格式字符串创建约束:
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format
options:(NSLayoutFormatOptions)opts
metrics:(NSDictionary *)metrics
views:(NSDictionary *)views
该方法返回一个NSLayoutConstraint对象数组——视觉化格式字符串可能同时创建多个约束。其中,第一个参数是视觉化格式字符串,第二、三个参数可以忽略,通常可以分别传入0和nil。第四个参数是视图名称字典,字典中包含视觉化格式字符串中需要使用的视图对象名称。例如,在下列的视觉化格式字符串中,包含imageView、dateLabel和toolbar三个视图对象名称,请注意,它们仅仅是一个字符串形式的名称而已。
@“H:|-[imageView]-|”
@“V:[dateLabel]-[imageView]-[toolbar]”
为了让自动布局系统知道这些名称所表示的具体视图对象,就需要通过视图名称字典将名称与视图对象关联起来。例如,字符串@“imageView”表示的是self.imageView。
在BNRDetailViewController.m中修改viewDidLoad方法,创建视图名称字典:
[self.view addSubview:iv];
self.imageView = iv;
NSDictionary *nameMap = @{ @“imageView” : self.imageView,
@“dateLabel” : self.dateLabel,
@“toolbar” : self.toolbar };
}
根据Apple命名规范,应该使用属性的名称或实例变量的名称作为视图对象的键。视觉化格式字符串将使用字典中的键表示相应的视图对象。
接下来为imageView添加水平和垂直两个方向上的约束,代码如下:
- (void)viewDidLoad
{
[super viewDidLoad];
…
NSDictionary *nameMap = @{ @“imageView” : self.imageView,
@“dateLabel” : self.dateLabel,
@“toolbar” : self.toolbar };
// imageView的左边和右边与父视图的距离都是0点
NSArray *horizontalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:
@“H:|-0-[imageView]-0-|”
options:0
metrics:nil
views:nameMap];
// imageView的顶边与dateLabel的距离是8点,底边与toolbar的距离也是8点
NSArray *verticalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:
@“V:[dateLabel]-[imageView]-[toolbar]”
options:0
metrics:nil
views:nameMap];
}