web-dev-qa-db-fra.com

Comment ajouter une contrainte par programme dans l'objectif c

Je veux ajouter une contrainte par programme et j'utilise le code ci-dessous pour ajouter une contrainte TOP et LEFT. 

NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:label1
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:self.view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:110];


NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:label1
                                                        attribute:NSLayoutAttributeLeading
                                                        relatedBy:NSLayoutRelationEqual
                                                           toItem:self.view
                                                        attribute:NSLayoutAttributeLeading
                                                       multiplier:1
                                                         constant:10];

lable1 est ajouté dans mon contrôleur de vue. Quand j'ajoute ces deux contraintes dans la vue comme 

[self.view addConstraint:top];
[self.view addConstraint:left];

Cela donne l'erreur dans la console et la contrainte n'affecte pas l'étiquette. 

2016-02-09 19:36:59.824 testinMRC[99160:313382] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>",
    "<NSIBPrototypingLayoutConstraint:0x7fa5c8628a70 'IB auto generated at build time for view with fixed frame' V:|-(88)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-02-09 19:36:59.889 testinMRC[99160:313382] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>",
    "<NSIBPrototypingLayoutConstraint:0x7fa5c86285c0 'IB auto generated at build time for view with fixed frame' H:|-(188)-[UILabel:0x7fa5c8626940'Label'](LTR)   (Names: '|':UIView:0x7fa5c86267b0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

Quelqu'un peut-il me dire pourquoi cette erreur survient? Aidez-moi à trouver la solution 

5
Crazy Developer

Dans votre cas, l'erreur indique clairement que vous avez des contraintes contradictoires. Probablement parce que vous essayez d'ajouter des contraintes à la vue qui en ont déjà depuis Interface Builder. Même si vous n’avez pas défini de contraintes, explicitement, IB vous les fournit lorsqu’il détecte qu’il en manque.

Je vois dans les commentaires que vous avez mentionnés que vous voulez tout faire par programmation. Dans ce cas, jetez un coup d'œil au code:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *view = [UIView new];
    view.backgroundColor = [UIColor redColor];

    [view setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.view addSubview:view];

    NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:100];
    NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:100];

    NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];
    NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];

    [self.view addConstraints:@[left, top]];
    [view addConstraints:@[height, width]];

}

C'est assez explicite. Comme vous pouvez le constater, j'ai dû ajouter des contraintes de largeur et de hauteur à la vue, car seules la gauche et le haut ne décrivent pas complètement sa position.

Résultat:

 enter image description here

Je vous encourage à essayer le langage de format visuel. Le même résultat peut être obtenu avec beaucoup moins de code. Ce code conduit au même résultat:

NSArray *horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|-100-[view(50)]" options:0 metrics:nil views:@{@"view" : view}];
NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[view(50)]" options:0 metrics:nil views:@{@"view" : view}];

[self.view addConstraints:vertical];
[self.view addConstraints:horizontal];

Faites-moi savoir si cela a aidé. À votre santé.

9
NKorotkov

Le problème n’est pas votre code, c’est le message IB auto generated at build time for view with fixed frame:

Interface Builder génère automatiquement des contraintes pour vous si vous ne les ajoutez pas vous-même.

  • Sélectionnez la plume ou le storyboard dans le navigateur de projet, accédez à l'inspecteur de fichiers et décochez Use Auto Layout.

ou

  • Ajoutez des contraintes dans Interface Builder et définissez-les sur remove at build time.
1
Jörn Buitink

Il semble que vous ayez des contraintes de mise en page en conflit. Une contrainte a probablement été configurée dans le storyboard et vous essayez d'ajouter une contrainte par programme qui entre directement en conflit avec elle.

On dirait que vous essayez de déplacer un UIView hors du chemin après une action. I. Appuyez sur un bouton et déplacez une image de visage joyeux du centre de l'écran vers le coin supérieur gauche.

Ajouter et supprimer des contraintes directement dans le code peut être un casse-tête énorme avec un gonflement du code, des tests unitaires et des avertissements remplissant votre console. 

Il serait peut-être préférable de créer UIView principal dans le storyboard et d’avoir un espace réservé UIView qui contient toutes les contraintes que vous souhaitez que UIView ait après l’appui sur le bouton. Ensuite, vous pouvez désactiver toutes les contraintes par programme pour ces vues UIV. Ainsi, la vue que vous souhaitez modifier aura la position, la largeur et la hauteur de l'espace réservé et l'emplacement aura la position et la hauteur de la vue que vous souhaitez modifier.

De cette manière, vous ne rencontrerez jamais cette erreur lors de la modification par programmation des contraintes de présentation, car toutes les erreurs seront capturées par le storyboard. 

Certains logiciels libres le font pour vous en une ou deux lignes de code. (Il y a aussi quelques tutoriels vidéo sur youtube dans la documentation) https://cocoapods.org/pods/SBP

Après avoir installé le cocoapod, votre code ressemblerait à ceci:

ce serait du code à l'intérieur du contrôleur de vue avec l'UIView que vous voulez modifier et l'espace réservé UIView

//UIView* viewBeforeChange
//UIView* hiddenViewAfterChange
[self switchViewConst:viewBeforeChange secondView:hiddenViewAfterChange];
0
Arjay Waran