'NSInvalidArgumentException', la raison: 'Impossible d'analyser la contrainte de format"
j'ai un sous-vu que je veux garder les arrêts pendant l'écran tournant, donc j'ai décidé de mettre le type NSLayoutConstraint:
espace de fuite vers Superview
espace supérieur à Superview
bouton espace à Superview
Je suis dans une sous-classe de Viewcell Utilisable. J'ai écrit le code, mais j'obtiens l'erreur suivante:
'NSInvalidArgumentException', reason: 'Unable to parse constraint format:
self is not a key in the views dictionary.
H:[self.arrows]-5-|
Mon code dans CustomCell.m est:
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 réponses
il semble que le moteur d'analyse de format visuel autolayout interprète le " .
"dans votre contrainte VFL comme un chemin de touche au lieu d'une clé comme si elle utilisait valueForKeyPath:
.
NSDictionaryOfVariableBindings(...)
prendra n'importe quel paramètre dans la parenthèse et le traduira dans une clé littérale avec l'objet comme valeur (dans votre cas: @{"self.arrow" : self.arrow}
). Dans le cas de la VFL, autolayout pense que vous avez une clé nommée self
à votre avis dictionnaire avec un subdictionnaire (ou sous-objet) qui a une clé de arrow
,
@{
@"self" : @{ @"arrow" : self.arrow }
}
quand vous avez littéralement voulu que le système interprète votre clé comme self.arrow
".
habituellement, quand j'utilise une variable d'instance getter comme ceci, je finis généralement par créer mon propre dictionnaire au lieu d'utiliser NSDictionaryOfVariableBindings(...)
comme ceci:
NSDictionary *views = @{ @"arrowView" : self.arrow }
ou
NSDictionary *views = NSDictionaryOfVariableBindings(_arrow);
qui vous permettrait de utilisez la vue dans votre VFL sans le soi et vous savez toujours de quoi vous parlez:
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views];
ou
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views];
en règle générale, j'ai appris à ne pas avoir de clés de dictionnaire avec un point ( .
) pour éviter toute confusion de système ou de débogage cauchemars.
mon truc est simplement de déclarer une variable locale qui n'est qu'un autre pointeur de la propriété, et de la mettre dans le 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);
le suffixe P
est pour "pointer".
la solution la plus simple est d'éviter les getters pour les variables de votre propre classe et de redéfinir les variables des superclasses comme des variables locales. Une solution pour votre exemple est
UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);
assurez-vous d'ajouter les contraintes après avoir ajouté le sous-vue requis à votre vue principale.Il a fallu un certain temps obtenir des connaissances relatives à cette question .