'NSInvalidArgumentException', reason: 'Unable to parse constraint format'
It looks like that the autolayout visual format parsing engine is interpreting the ".
" in your VFL constraint to be a keyPath instead of a key like it's using valueForKeyPath:
.
NSDictionaryOfVariableBindings(...)
will take whatever your parameter is in the parenthesis and translate it into a literal key with the object as the value (in your case: @{"self.arrow" : self.arrow}
). In the case of the VFL, autolayout is thinking that you have a key named self
in your view dictionary with a subdictionary (or subobject) that has a key of arrow
,
@{
@"self" : @{ @"arrow" : self.arrow }
}
when you literally wanted the system to interpret your key as "self.arrow
".
Usually, when I'm using a instance variables getter like this, I typically end up creating my own dictionary instead of using NSDictionaryOfVariableBindings(...)
like so:
NSDictionary *views = @{ @"arrowView" : self.arrow }
or
NSDictionary *views = NSDictionaryOfVariableBindings(_arrow);
Which would allow you to use the view in your VFL without the self and you still know what you're talking about:
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views];
or
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views];
As a general rule, I've learned not to have dictionary keys with a dot (.
) in them to avoid any system confusion or debugging nightmares.
My trick is to simply declare a local variable that's just another pointer to the property, and put it in the NSDictionaryOfVariableBindings
.
@interface ViewController ()
@property (strong) UIButton *myButton;
@property (strong) UILabel *myLabel;
@end
...
UIButton *myButtonP = self.myButton;
UILabel *theLabelP = self.myLabel;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(myButtonP, myLabelP);
The P
suffix is for "pointer".
Easiest solution is to avoid the getters for variables from your own class and redefine variables from superclasses as local variables. A solution for your example is
UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);