I have a subview that I want to keep stops during rotating screen, so I decided to put the NSLayoutConstraint type:
Trailing Space to Superview
Top Space to Superview
Button Space to Superview
I'm in a subclass of UITableViewCell. I wrote the code but I get the following error:
'NSInvalidArgumentException', reason: 'Unable to parse constraint format:
self is not a key in the views dictionary.
H:[self.arrows]-5-|
My code in CustomCell.m is:
self.arrows = [[Arrows alloc]initWithFrame:CGRectMake(self.contentView.bounds.size.width-30, self.bounds.origin.y+4, 30, self.contentView.bounds.size.height-4)];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self.arrows, self.contentView);
NSMutableArray * constraint=[[NSMutableArray alloc]init];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H: [self.arrows]-5-|" options:0 metrics:nil views:viewsDictionary]];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-1-[self.arrows]" options:0 metrics:nil views:viewsDictionary]];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"[V: [self.arrows]-1-|" options:0 metrics:nil views:viewsDictionary]];
[self.arrows addConstraints:constraint];
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
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 usingvalueForKeyPath:
.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 namedself
in your view dictionary with a subdictionary (or subobject) that has a key ofarrow
,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:or
Which would allow you to use the view in your VFL without the self and you still know what you're talking about:
or
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.Make sure you add the constraints after adding the required subview to your main view.It took a while get knowledge relating to this issue .
My trick is to simply declare a local variable that's just another pointer to the property, and put it in the
NSDictionaryOfVariableBindings
.The
P
suffix is for "pointer".