83 votes

Centrer le X d'une sous-vue dans l'autolayout génère un message "non préparé pour la contrainte".

J'ai une sous-classe UIView personnalisée qui est initialisée via une nib.

En -awakeFromNib Je crée une vue secondaire et j'essaie de la centrer dans sa vue secondaire.

[self setInteralView: [[UIView alloc] init]];
[[self internalView] addConstraint: [NSLayoutConstraint constraintWithItem: [self internalView]
                                                                 attribute: NSLayoutAttributeCenterX
                                                                 relatedBy: NSLayoutRelationEqual
                                                                    toItem: self
                                                                 attribute: NSLayoutAttributeCenterX
                                                                multiplier: 1
                                                                  constant: 0]];

Cette opération est interrompue et donne lieu à la sortie suivante :

2013-08-11 17:58:29.628 MyApp[32414:a0b] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2013-08-11 17:58:29.630 MyApp[32414:a0b] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    Container hierarchy: 
<UIView: 0xc132a40; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0xc132bc0>>
    View not found in container hierarchy: <MyView: 0xc1315a0; frame = (-128 -118; 576 804); layer = <CALayer: 0xc131710>>
    That view's superview: <UIView: 0xc131a70; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xc131b50>>

117voto

JannieT Points 2160

Pour les autres personnes qui viennent ici : J'ai obtenu cette erreur parce que j'ai ajouté les contraintes avant d'ajouter les sous-vues à la hiérarchie.

96voto

Charles A. Points 971

Comme l'indique l'erreur, vous devez ajouter la contrainte à une vue telle que les vues impliquées dans la contrainte soient la vue à laquelle vous l'ajoutez ou une sous-vue de cette vue. Dans le cas de votre code ci-dessus, vous devez ajouter cette contrainte à self plutôt que [self internalView] . La raison pour laquelle cela ne fonctionne pas comme écrit est que l'une des vues impliquées dans la contrainte ( self ) n'est pas dans la hiérarchie des vues si l'on ne considère que les [self internalView] et ci-dessous).

Pour plus de détails, voir le section de discussion de la documentation sur le addConstraint: méthode.

Voici votre ligne de code, corrigée comme je le suggère :

UIView* internalView = [[UIView alloc] initWithFrame:CGRectZero];
internalView.translatesAutoresizingMaskIntoConstraints = NO;
[self setInternalView:internalView];

[self addConstraint: [NSLayoutConstraint constraintWithItem: [self internalMapView]
                                         attribute: NSLayoutAttributeCenterX
                                         relatedBy: NSLayoutRelationEqual
                                         toItem: self
                                         attribute: NSLayoutAttributeCenterX
                                         multiplier: 1
                                         constant: 0]];

36voto

Réponse courte : échange vue parentale et vue enfantine.
Assumer self est la vue parentale :

  • mauvais : [subview addConstraint [NSLayoutConstraint constraintWithItem:self...

  • bon : [self addConstraint [NSLayoutConstraint constraintWithItem:subview...


Swift

subview.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
    "H:|-0-[subview]-0-|",
    options: .DirectionLeadingToTrailing,
    metrics: nil,
    views: ["subview":subview]))

Obj-C

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addConstraints:[NSLayoutConstraint
                      constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                      options:NSLayoutFormatDirectionLeadingToTrailing
                      metrics:nil
                      views:NSDictionaryOfVariableBindings(subview)]];

10voto

Kevin Points 175

Conseils supplémentaires :

J'ai une application récemment développée qui fonctionne bien sur iOS7 mais qui obtient une erreur sur iOS8 "The view hierarchy is not prepared for the constraint".

J'ai lu dans un autre article que les (sous-)vues devaient être ajoutées avant de créer les contraintes. C'est ce que j'ai fait mais j'ai toujours l'erreur.

J'ai ensuite compris que je devais créer des contraintes sous -(void)viewDidAppear au lieu de viewDidLoad.

6voto

WongWray Points 507

Il s'agit d'une vieille question, mais je tiens à souligner cette ligne de la documentation :

Lorsque vous développez pour iOS 8.0 ou une version ultérieure, attribuez la valeur true à la propriété isActive de la contrainte au lieu d'appeler directement la méthode addConstraint(_ :). La propriété isActive ajoute et supprime automatiquement la contrainte de la vue correcte.

Au moins, cela élimine un point de défaillance puisque vous n'avez plus à vous soucier d'appeler addConstraint sur la mauvaise vue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X