'NSInvalidArgumentException',原因:'无法解析约束格式'

时间:2012-10-24 08:09:46

标签: ios layout compiler-errors constraints autolayout

我有一个子视图,我想在旋转屏幕期间停止,所以我决定放置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];

4 个答案:

答案 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)

确保在将所需的子视图添加到主视图后添加约束。花了一段时间获取有关此问题的知识。