2012-10-24 7 views
50

Ich habe ein Subview, die ich will Anschläge halten Bildschirm während der Rotation, so dass ich beschloss, den NSLayoutConstraint Typen zu setzen:

nachstehendes Leerzeichen
Top zu Super Space to Superview
Button Space zu Superview
Ich bin in einer Unterklasse von UITableViewCell. Ich schrieb den Code, aber ich erhalte die folgenden Fehler:
‚NSInvalidArgumentException‘ Grund: ‚Kann nicht Constraint-Format analysieren‘

'NSInvalidArgumentException', reason: 'Unable to parse constraint format: 
self is not a key in the views dictionary. 
H:[self.arrows]-5-| 


Mein Code in CustomCell.m ist:

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

Antwort

121

Es sieht so aus, dass das automatische Layout visuelles Format Parsing-Engine die interpretiert "." in Ihrer VFL-Einschränkung, um ein keyPath anstelle eines Schlüssels zu sein, wie es valueForKeyPath: verwendet.

NSDictionaryOfVariableBindings(...) nehmen, was auch immer Ihr Parameter in der Klammer ist und übersetzen Sie es in einen Literalschlüssel mit dem Objekt als Wert (in Ihrem Fall: @{"self.arrow" : self.arrow}). Im Falle des VFL, automatischen Layout ist zu denken, dass Sie einen Schlüssel self Ihrer Ansicht Wörterbuch mit einem subdictionary (oder Subobjekt), die einen Schlüssel von arrow hat,

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

, wenn Sie buchstäblich das System wollte zu interpretieren genannt haben Ihr Schlüssel als "self.arrow".

Normalerweise, wenn ich eine Instanzvariablen Getter wie diese verwenden, ich am Ende normalerweise mein eigenes Wörterbuch zu schaffen, anstatt NSDictionaryOfVariableBindings(...) der Verwendung von in etwa so:

NSDictionary *views = @{ @"arrowView" : self.arrow } 

oder

NSDictionary *views = NSDictionaryOfVariableBindings(_arrow); 

Was würde können Sie die Ansicht in Ihrem VFL ohne das Selbst verwenden und Sie wissen immer noch, wovon Sie sprechen:

NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views]; 

oder

NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views]; 

In der Regel habe ich gelernt, nicht Dictionary-Schlüssel mit einem Punkt (.) in ihnen haben jedes System Verwirrung oder Debuggen Alpträume zu vermeiden.

+1

Vielen Dank –

+25

ziemlich lächerlich, dass die docs Beispiele geben von 'NSDictionaryOfVariableBindings' mit dem Wörterbuch zu erstellen, aber nicht erwähnen, dass es nicht mit einer Eigenschaft oder IBOutlets arbeiten –

+0

Jonathan, ich war selbst ziemlich verwirrt. Die Dokumente geben ausdrücklich an, diese Methode zu verwenden. Ich dachte nur, es war schlau genug, um das Selbst zu entfernen. Teil des Schlüssels automatisch. – Nailer

7

Mein Trick besteht darin, einfach eine lokale Variable zu deklarieren, die nur ein weiterer Zeiger auf die Eigenschaft ist, und sie in die NSDictionaryOfVariableBindings einzufügen.

@interface ViewController() 
@property (strong) UIButton *myButton; 
@property (strong) UILabel *myLabel; 
@end 

... 

UIButton *myButtonP = self.myButton; 
UILabel *theLabelP = self.myLabel; 
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(myButtonP, myLabelP); 

Das P Suffix ist für "Zeiger".

+2

Dies negiert den Punkt von NSDictionaryOfVariableBindings, der Dinge kürzer machen soll. Warum nicht 'NSDictionary * views = @ {@" myButton ": self.myButton, @" myLabel ": self.myLabel}' statt? Es ist kürzer. –

+0

Es negiert den Punkt überhaupt nicht, wenn Sie eine lange Liste anderer Ansichten haben und einen Verweis auf 'self.view' einfügen möchten. – davidf2281

+0

warum dies anstelle von _myButton und _myLabel? oder synthetisieren, um Ivars anders zu benennen? –

-1

Stellen Sie sicher, dass Sie die Einschränkungen hinzufügen, nachdem Sie der Hauptansicht die erforderliche Unteransicht hinzugefügt haben. Es hat eine Weile gedauert, bis Sie sich mit diesem Problem vertraut gemacht haben.

1

Die einfachste Lösung besteht darin, die Getter für Variablen aus Ihrer eigenen Klasse zu vermeiden und Variablen aus Oberklassen als lokale Variablen neu zu definieren.Eine Lösung für Ihr Beispiel ist

UIView *contentView = self.contentView; 
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView); 
Verwandte Themen