web-dev-qa-db-ja.com

「NSInvalidArgumentException」、理由:「制約形式を解析できません」

画面の回転中に停止を維持したいサブビューがあるため、NSLayoutConstraintタイプを配置することにしました。

トレーリングスペースからスーパービュー
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];
50
user1747321

自動レイアウト視覚形式解析エンジンは、VFL制約の「_._」を、_valueForKeyPath:_を使用しているようなキーではなく、keyPathとして解釈しているようです。

NSDictionaryOfVariableBindings(...)は、括弧内のパラメーターが何であっても、オブジェクトを値としてリテラルキーに変換します(場合:_@{"self.arrow" : self.arrow}_)。 VFLの場合、オートレイアウトは、ビュー辞書にselfというキーを持つサブディクショナリ(またはサブオブジェクト)を持つarrowという名前のキーがあると考えています。

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

文字通りシステムにキーを「_self.arrow_」として解釈させたいとき。

通常、このようなインスタンス変数ゲッターを使用している場合、通常、次のように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];
_

一般的なルールとして、システムの混乱や悪夢のデバッグを避けるために、ドット(_._)を含む辞書キーを持たないことを学びました。

121
larsacus

私のコツは、プロパティへの単なる別のポインタであるローカル変数を単純に宣言し、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接尾辞は「ポインタ」用です。

7
Eric

最も簡単な解決策は、独自のクラスの変数のゲッターを回避し、スーパークラスの変数をローカル変数として再定義することです。あなたの例の解決策は

UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);
1
Mihai Damian