Mise en page craquée

J'ai le controller de vue artificiel suivant:

@interface ViewController () @property (nonatomic, strong) IBOutlet UILabel *l1; @property (nonatomic, strong) IBOutlet UILabel *l2; @property (nonatomic, strong) IBOutlet UITextField *input1; @property (nonatomic, strong) IBOutlet UITextField *input2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view removeConstraints:self.view.constraints]; for (UIView *view in @[self.l1, self.l2, self.input1, self.input2]) [view setTranslatesAutoresizingMaskIntoConstraints:NO]; NSDictionary *views = @{ @"l1" : self.l1, @"l2" : self.l2, @"input1": self.input1, @"input2" : self.input2, @"topLayout" : self.topLayoutGuide}; NSArray *constraints; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[l1]-[input1]" options:NSLayoutFormatAlignAllCenterY mesortingcs:nil views:views]; [self.view addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[l2]-[input2]" options:NSLayoutFormatAlignAllCenterY mesortingcs:nil views:views]; [self.view addConstraints:constraints]; NSSsortingng *v1 = @"V:|-20-[input1]-[input2]"; constraints = [NSLayoutConstraint constraintsWithVisualFormat:v1 options:0 mesortingcs:nil views:views]; [self.view addConstraints:constraints]; NSSsortingng *v2 = @"V:|-20-[l1]-[l2]"; constraints = [NSLayoutConstraint constraintsWithVisualFormat:v2 options:0 mesortingcs:nil views:views]; [self.view addConstraints:constraints]; } @end 

Ce qui entraîne la sortie suivante:

entrez la description de l'image ici

Si je change simplement v1 et v2 pour utiliser le topLayoutGuide:

 NSSsortingng *v1 = @"V:[topLayout]-20-[input1]-[input2]"; NSSsortingng *v2 = @"V:[topLayout]-20-[l1]-[l2]"; 

L'écran semble tout froissé comme ceci:

entrez la description de l'image ici

Je peux get ce pour disparaître quand j'arrête d'utiliser NSLayoutFormatAlignAllCenterY sur mes contraintes horizontales, mais alors mes lignes ne s'alignent plus correctement:

entrez la description de l'image ici

Pourquoi ce problème se produit-il, et quelle serait l'approche appropriée pour aligner correctement les lignes tout en utilisant le topLayoutGuide?

Le problème, en un mot, est que vous ne comprenez pas la relation entre les contraintes générées par le storyboard / nib à travers la layout automatique et les contraintes générées par votre code. Vos contraintes étaient donc toujours mauvaises (même lorsque la layout visuelle semblait correcte). Le problème avec le guide de layout supérieur a simplement provoqué la méchanceté visuelle de vos contraintes.

Cependant, je préférerais ne pas insister sur ce point (c.-à-d. Tout ce que votre code faisait mal); Je préfère sauter directement à la bonne approche. Prêt? Faites simplement comme suit:

  1. Dans votre code, supprimez cette ligne (qui était en fait la cause de 90% du problème):

     [self.view removeConstraints:self.view.constraints]; 
  2. Dans le storyboard:

    une. Donnez à chacun des quatre éléments (les deux labels et les deux champs de text) une contrainte de gauche (menant) et une contrainte supérieure.

    b. Sélectionnez les huit contraintes que vous venez de créer et, dans l'inspecteur des attributes, cochez la case "Supprimer au moment de la construction".

Maintenant, votre code fonctionnera exactement comme vous le désirez.

Comme je l'ai dit, je préférerais ne pas trop vous expliquer pourquoi, mais ce que je vous ai demandé de faire est de créer correctement des vues dans le storyboard / nib sous autolayout et de ne pas appliquer ces contraintes aux vues. généré dans le code.


Veuillez noter que vous pouvez également supprimer cette ligne:

 for (UIView *view in @[self.l1, self.l2, self.input1, self.input2]) [view setTranslatesAutoresizingMaskIntoConstraints:NO]; 

Ça ne fait pas de mal, mais ça ne va pas non plus, car ces vues ne traduisent pas déjà leur masque autoresizing en contraintes.


Une dernière remarque: tout ce que nous venons de faire est extrêmement stupide, puisque vous auriez pu prendre l'une des deux approches les plus habituelles:

  • Nous aurions pu générer toutes ces contraintes dans le storyboard / nib et simplement supprimer tout votre code.

  • Ou, au contraire, nous aurions pu supprimer les sous-vues du storyboard / nib et créer les sous-vues dans le code (et les append à self.view dans le code).

L'un ou l'autre de ceux-ci aurait signifié que votre code aurait fonctionné correctement (à l'exception de la partie sur la suppression de toutes les contraintes, ce qui était toujours une idée désastreuse). Cependant, je vous ai montré comment faire ce que vous essayiez de faire, simplement pour aller de l'avant avec l'hypothèse.