There are times when a constraint cannot be created with a visual format string. For instance, you cannot use VFL to create a constraint based on a ratio, like if you wanted the date label to be twice as tall as the name label or if you wanted the image view to always be 1.5 times as wide as it is tall.
In these cases, you can create an instance of NSLayoutConstraint using the method
+ (id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
This method creates a single constraint using two layout attributes of two view objects. The multiplier is the key to creating a constraint based on a ratio. The constant is a fixed number of points, like you have used in your spacing constraints.
The layout attributes are defined as constants in the NSLayoutConstraint class:
NSLayoutAttributeLeft
NSLayoutAttributeRight
NSLayoutAttributeTop
NSLayoutAttributeBottom
NSLayoutAttributeWidth
NSLayoutAttributeHeight
NSLayoutAttributeBaseline
NSLayoutAttributeCenterX
NSLayoutAttributeCenterY
NSLayoutAttributeLeading
NSLayoutAttributeTrailing
Let’s consider a hypothetical constraint.
Say you wanted the image view to be 1.5
times as wide as it is tall.
You cannot do this with a visual format string, so you would create it individually instead with the following code.
(Do not type this hypothetical constraint in your code! It will conflict with others you already have.)
NSLayoutConstraint *aspectConstraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeHeight multiplier:1.5 constant:0.0];
To understand how this method works, think of this constraint as the equation shown in Figure 16.4.
You relate a layout attribute of one view to the layout attribute of another view using a multiplier and a constant to define a single constraint.
To add a single constraint to a view, you use the method
- (void)addConstraint:(NSLayoutConstraint *)constraint
The same logic applies to decide which view should receive this message. When using this method, the determination is even easier to make because the affected view objects are the first and fourth arguments. In this case, the only affected object is the image view, so you would add aspectConstraint to that view:
[self.imageView addConstraint:aspectConstraint];