I'm trying to set top and bottom paddings to a view in Autolayout using the visual format language. The code compiles and works if I write the paddings as integers in visual format string, but it fails when I try to replace it with a constant. Here's the error I'm getting:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse constraint format: It's not possible to set a space equal to the width or height of a view. Perhaps you want to use a view as a spacer? [view1][spacer(==view1)][view2] V:|-kTopAndBottomPadding-[messageTextView]-kTopAndBottomPadding-|
And this is my code.
CGFloat const SPMTVC_kTopAndBottomPadding = 5.0;
// ...
// Create my own NSDictionary of variable bindings.
NSDictionary *variableBindings = @{@"messageTextView" : _messageTextView,
@"contentView" : self.contentView,
@"kTopAndBottomPadding" : [NSNumber numberWithFloat:SPMTVC_kTopAndBottomPadding]};
// Constraints in the horizontal axis.
// Basically just pins the view to the left and right of superview.
NSMutableArray *constraints = [[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-0-[messageTextView(==contentView)]-0-|"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:variableBindings] mutableCopy];
// Constraints in vertical axis, give 5-point padding from superview's top & bottom.
[constraints addObjectsFromArray:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-kTopAndBottomPadding-[messageTextView]-kTopAndBottomPadding-|"
options:NSLayoutFormatAlignAllTop
metrics:nil
views:variableBindings]];
for (NSLayoutConstraint *constraint in constraints) {
[self.contentView addConstraint:constraint];
}
I think the error message means that the compiler thinks kTopAndBottomPadding
is a UIView
, when it's an NSNumber
as defined in the dictionary. Is there a way to do this right?
This is what the metrics dictionary is for. So for example, if you want to use "padding" as a constant in your VFL string, do something like this:
[constraints addObjectsFromArray:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-padding-[messageTextView]-kTopAndBottomPadding-|"
options:NSLayoutFormatAlignAllTop
metrics:@{@"padding":@5}
views:variableBindings]];
You need to pass kTopAndBottomPadding
in the metrics dictionary, not the views dictionary.
Also, you might want to just take advantage of the addConstraints:
method instead of messing about with mutable arrays and for
/in
loops.
CGFloat const SPMTVC_kTopAndBottomPadding = 5.0;
// ...
NSDictionary *metrics = @{
@"kTopAndBottomPadding" : @(SPMTVC_kTopAndBottomPadding)
};
NSDictionary *views = @{
@"messageTextView" : _messageTextView,
@"contentView" : self.contentView
};
[self.contentView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-0-[messageTextView(==contentView)]-0-|"
options:NSLayoutFormatAlignAllLeading
metrics:metrics views:views]];
[self.contentView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-kTopAndBottomPadding-[messageTextView]-kTopAndBottomPadding-|"
options:NSLayoutFormatAlignAllTop
metrics:metrics views:views]];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With