50

我有一个子视图,我想在旋转屏幕期间保持停止,所以我决定将 NSLayoutConstraint 类型:

拖尾空间到 Superview
顶部空间到 Superview
按钮空间到 Superview
我在 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

4 回答 4

120

看起来自动布局视觉格式解析引擎正在将.VFL 约束中的 "" 解释为 keyPath 而不是它使用的键valueForKeyPath:

NSDictionaryOfVariableBindings(...)将采用括号中的任何参数并将其转换为以对象为值的文字键(在您的情况下为:)@{"self.arrow" : self.arrow}。在 VFL 的情况下,自动布局认为您有一个self在视图字典中命名的键,其子字典(或子对象)的键为arrow,

@{
   @"self" : @{ @"arrow" : self.arrow }
}

当您真正希望系统将您的密钥解释为“ self.arrow”时。

通常,当我使用这样的实例变量 getter 时,我通常最终会创建自己的字典,而不是NSDictionaryOfVariableBindings(...)像这样使用:

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];

作为一般规则,我已经学会了不要.在其中使用带有点 ( ) 的字典键,以避免任何系统混乱或调试噩梦。

于 2012-10-24T17:35:18.903 回答
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后缀是“指针” 。

于 2013-10-07T12:31:38.103 回答
1

最简单的解决方案是避免从您自己的类中获取变量,并将超类中的变量重新定义为局部变量。您的示例的解决方案是

UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);
于 2014-09-09T08:48:32.637 回答
-1

确保在将所需的子视图添加到主视图后添加约束。需要一段时间才能获得与此问题相关的知识。

于 2014-06-16T12:03:40.370 回答