我有一个子视图,我想在旋转屏幕期间停止,所以我决定放置NSLayoutConstraint类型:
超级视图的尾随空间
超级视图的顶级空间
超级视图的按钮空间
我在UITableViewCell的子类中。我写了代码,但是我收到以下错误:
'NSInvalidArgumentException', reason: 'Unable to parse constraint format:
self is not a key in the views dictionary.
H:[self.arrows]-5-|
我在CustomCell.m中的代码是:
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];
答案 0 :(得分:121)
看起来autolayout可视格式解析引擎将VFL约束中的“.
”解释为keyPath而不是像使用valueForKeyPath:
那样的键。
NSDictionaryOfVariableBindings(...)
将取括号中的参数,并将其转换为文字键,并将对象作为值(在您的情况下为@{"self.arrow" : self.arrow}
)。在VFL的情况下,autolayout认为您的视图字典中有一个名为self
的键,其子字典(或子对象)的键为arrow
,
@{
@"self" : @{ @"arrow" : self.arrow }
}
当您真正希望系统将您的密钥解释为“self.arrow
”时。
通常,当我使用像这样的实例变量getter时,我通常最终创建自己的字典而不是像NSDictionaryOfVariableBindings(...)
这样使用{/ p>
NSDictionary *views = @{ @"arrowView" : self.arrow }
或
NSDictionary *views = NSDictionaryOfVariableBindings(_arrow);
这将允许你在没有自我的情况下使用你的VFL视图,你仍然知道你在说什么:
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views];
或
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views];
作为一般规则,我已经学会了不要在其中包含带点(.
)的字典键,以避免任何系统混淆或调试恶梦。
答案 1 :(得分:7)
我的诀窍是简单地声明一个局部变量,它只是另一个指向该属性的指针,并将其放在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);
P
后缀用于“指针”。
答案 2 :(得分:1)
最简单的解决方案是避免从您自己的类中获取变量的getter,并将超类中的变量重新定义为局部变量。您的示例的解决方案是
UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);
答案 3 :(得分:-1)
确保在将所需的子视图添加到主视图后添加约束。花了一段时间获取有关此问题的知识。