Reputation: 7826
HI I am setting my views using autoLayouts with visual format language.
I add some constraints to my views.
Here are my codes how I set up:
- (void)viewDidLoad
{
self.first = [UIView new];
self.second = [UIView new];
self.third = [UIView new];
self.fourth = [UIView new];
self.fifth = [UIView new];
self.first.translatesAutoresizingMaskIntoConstraints = NO;
self.second.translatesAutoresizingMaskIntoConstraints = NO;
self.third.translatesAutoresizingMaskIntoConstraints = NO;
self.fourth.translatesAutoresizingMaskIntoConstraints = NO;
self.fifth.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.first];
[self.view addSubview:self.second];
[self.view addSubview:self.third];
[self.view addSubview:self.fourth];
[self.view addSubview:self.fifth];
NSDictionary *dictionary = NSDictionaryOfVariableBindings(_first, _second, _third, _fourth, _fifth);
NSArray *constraintsArray;
NSString *format;
format = @"|[_first][_second][_third][_fourth][_fifth]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
format = @"V:|[_first]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
format = @"V:|[_second]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
format = @"V:|[_third]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
format = @"V:|[_fourth]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
format = @"V:|[_fifth]|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:dictionary];
[self.view addConstraints:constraintsArray];
}
Here is what i want the five UIView
s act as. They have same WIDTH and HEIGHT and there are no margin on both size.(The first one and the last one) . That's say, they are filled within there container view, in this case, (self.view)
When I run, the app crash:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse constraint format:
Options mask required views to be aligned on a horizontal edge, which is not allowed for layout that is also horizontal.
|[_first][_second][_third][_fourth][_fifth]|
^'
What I had done wrong? Please help me. Thanks.
Upvotes: 2
Views: 1035
Reputation:
format string proposed by Rob is perfect. You can also avoid all the other vertical constraints just adding 'NSLayoutFormatAlignAllTop' instead of 'NSLayoutFormatAlignAllLeft'. Basically when you deal with a format string related to horizontal axis you must use alignment options that relate to vertical axis and vice versa ( option is perpendicular to format string ), or if you don't need it just pass 0. Your only one method should look like this:
NSString format = @"H:|[_first][_second(==_first)][_third(==_first)][_fourth(==_first)][_fifth(==_first)]|";
[NSLayoutConstraint constraintsWithVisualFormat:format
options:NSLayoutFormatAlignAllTop
metrics:nil
views:dictionary];
[EDIT]
Rob's right. NSLayoutFormatAlignAllTop aligns all top side of views inside the format string between them and not to their superview. You have to add one vertical pin constraint to only one of your view and all the others will also align because of 'NSLayoutFormatAlignAllTop'. Also to remove ambiguous layout you need to add a height constraint. This is the code i tried (with a 100 point height) and doesn't give me ambiguous layout:
NSDictionary *dictionary = NSDictionaryOfVariableBindings(_first, _second, _third, _fourth, _fifth);
NSString *format = @"H:|[_first][_second(==_first)][_third(==_first)][_fourth(==_first)][_fifth(==_first)]|";
NSMutableArray *constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format
options:NSLayoutFormatAlignAllTop
metrics:nil
views:dictionary].mutableCopy;
[constraintsArray addObject:[NSLayoutConstraint constraintWithItem:_first
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:_first.superview
attribute:NSLayoutAttributeTop
multiplier:1.0 constant:0]];
CGFloat height = 100;
for (UIView *view in @[_first,_second,_third,_fourth,_fifth]) {
[constraintsArray addObject:[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:height]];
}
[self.view addConstraints:constraintsArray];
Upvotes: 1
Reputation: 437882
You should remove all of those references to NSLayoutFormatAlignAllLeft
.
Also, unrelated, but you are missing the constraint that makes them the same width. I'd replace the horizontal constraint with:
format = @"H:|[_first][_second(==_first)][_third(==_first)][_fourth(==_first)][_fifth(==_first)]|";
Upvotes: 4