La difficulté avec mise en page automatique sur UITableViewCell
Je vais avoir des ennuis avec mise en page automatique sur un xcode 5
projet. Je suis en utilisant un simple vue-contrôleur à l'intérieur avec une manette de navigation. J'ai un MKMapView
sur la moitié supérieure et une UITableView
sur la moitié inférieure. Je suis à l'aide de storyboards
, et que vous avez configuré le prototype UITableViewCell
, mais je suis ajoutant des contraintes à l'aide de code. J'ai vérifié tous les contrôles dans le prototype et ne vois pas de contraintes configuré. Mon problème survient lorsque je ajouter des contraintes pour le UITableViewCell
. J'ai le code suivant dans les cellules:
-(void)updateConstraints {
[super updateConstraints];
//first remove old constraints
[self removeConstraints:self.constraints];
[self.nameLabel removeConstraints:self.nameLabel.constraints];
[self.addressLabel removeConstraints:self.nameLabel.constraints];
[self.rentableSquareFeetLabel removeConstraints:self.rentableSquareFeetLabel.constraints];
[self.lastSaleAmountLabel removeConstraints:self.lastSaleAmountLabel.constraints];
[self.lastSaleDateLabel removeConstraints:self.lastSaleAmountLabel.constraints];
[self.thumbnailImageView removeConstraints:self.thumbnailImageView.constraints];
//then set up constraints
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_thumbnailImageView, _nameLabel, _rentableSquareFeetLabel, _lastSaleAmountLabel, _addressLabel, _lastSaleDateLabel);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_thumbnailImageView(60)]-[_nameLabel(<=200)]-(>=8)-[_rentableSquareFeetLabel]-(>=8)-[_lastSaleAmountLabel]|" options:0 metrics:nil views:viewsDictionary]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_nameLabel]-(-4)-[_addressLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_lastSaleAmountLabel]-(-4)-[_lastSaleDateLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]];
}
Je suis arriver au suivant dans la console de débogage. L'exception est déclenchée par la première addConstraints ligne. Si j'ai tout simplement continuer à travers ces puis finalement tout s'affiche comme il se doit, comme il semble que xcode est le choix de rompre la bonne contrainte:
2013-09-25 15:07:14.169 PECProperties[32381:a0b] 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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) (
"<NSIBPrototypingLayoutConstraint:0x9d56c70 'IB auto generated at build time for view with fixed frame' H:|-(0)-[UIImageView:0x9d558f0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620 )>",
"<NSIBPrototypingLayoutConstraint:0x9d56d20 'IB auto generated at build time for view with fixed frame' H:[UIImageView:0x9d558f0(60)]>",
"<NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620 )>",
"<NSLayoutConstraint:0x9d53830 H:[UIImageView:0x9d558f0]-(NSSpace(8))-[UILabel:0x9d559e0]>" )
Will attempt to recover by breaking constraint <NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620 )>
Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
La troisième NSIBPrototypingLayoutConstraint montre que 78 points entre le bord de la vue et une étiquette. C'est là que le prototype est positionné à peu près (et si je la déplace dans le prototype, je vois la variation de la contrainte dans la console de débogage), mais qui est en conflit avec mon propre contrainte de distance "standard" entre l'affichage de l'image et de l'étiquette.
J'ai essayé le réglage de la translatesAutoresizingMaskIntoConstraints=NO
dans la vue du contrôleur de cellForRowAtIndexPath
, mais qui ne semble pas être l'aider non plus. Comment puis-je corriger la mise en page?
- J'ai remarqué un tout-en-un bug dans iOS7 qui a causé un problème similaire. J'étais en précisant toutes les contraintes de l'IB et XCode était heureux. Mais la somme de toutes les verticales tailles à l'exception < la hauteur de la cellule. La solution a été la un - pour supprimer une des contraintes au moment de la construction.
Vous devez vous connecter pour publier un commentaire.
Quelques choses à couvrir ici:
La
NSIBPrototypingLayoutConstraint
contraintes que vous rencontrez (et qui sont à l'origine des exceptions) sont auto-générés par Interface Builder afin de faire de votre Storyboard ou XIB la disposition de l'affichage non-ambiguë. C'est assez sournois à ce sujet, mais il est automatiquement ajoutant le minimum de contraintes nécessaires, afin que la position et la taille de chaque ambigu vue devient complètement spécifié. C'est un changement de Xcode 4, parce que dans Xcode 4 vous ne pourriez pas avoir ambigu mises en page dans Interface Builder. Avec Xcode 5 et les versions ultérieures vous pouvez, cependant, de la dge, de générer automatiquement ces contraintes pour vous si votre mise en page est ambigu au moment de la compilation.La façon de résoudre ce problème est d'ajouter le minimum requis contraintes dans Interface Builder, de sorte que chaque point de vue la position de & la taille est complètement spécifié, puis sélectionnez chacun de ces indésirables contraintes, aller à la barre latérale de droite Attributs de l'inspecteur, et cochez la case à côté de espace Réservé - Retirer au moment de la construction.
Non seulement cette case à cocher supprimer la contrainte que vous avez ajouté, mais plus important encore, il permettra d'éviter l'auto-générés IB contrainte de prendre sa place! (Comme vous pouvez l'imaginer, c'est assez fastidieux quand vous avez un certain nombre de vues de l'IB et pouvez gérer tous vos contraintes dans le code. Pour cette raison, vous voudrez peut-être éviter à l'aide de l'IB entièrement pour visualiser des hiérarchies dans lesquelles vous avez l'intention de mettre en œuvre Mise en page Automatique par programmation.)
Quelle est la différence entre un espace Réservé contrainte et une Désinstallé contrainte? Voici une diapositive à partir de mon Adaptative Mise en page Automatique de parler (vidéo) (Diapositives en format PDF) en comparant les deux:
Dans
updateConstraints
, vous ne voulez pas supprimer les contraintes et rajoutez-les comme vous avez là. Pourquoi pas? Essentiellement, c'est terrible pour la performance, et j'ai confirmé avec les ingénieurs d'Apple que ce n'est pas une bonne idée. Voir la question/réponse que j'ai posté ici pour plus de détails, ainsi que ce réponse. Pour éviter les contraintes d'être ajouté plus d'une fois, l'utilisation d'un indicateur booléen (par exemplehasSetupConstraints
) que vous avez défini sur OUI, une fois que vous avez configuré vos contraintes la première fois, et siupdateConstraints
est appelée de nouveau, vous pouvez simplement retourner immédiatement si vous n'avez pas de nouvelles contraintes à ajouter. Voir cette question pour la poursuite des discussions.Le code que vous utilisez pour supprimer les contraintes peuvent ne pas fonctionner complètement. C'est parce que
[view removeConstraints:view.constraints]
ne supprime que les contraintes qui ont été ajoutés àview
-- rappelez-vous que les contraintes peuvent être ajoutées à toute commune superview du point de vue de contraindre -- et les contraintes ajoutées àview
peuvent ne pas être les seuls à modifier la disposition desview
! Si vous avez besoin de supprimer un certain nombre de contraintes, vous devez stocker une référence à chacune de ces contraintes dans une propriété (par exemple, un NSArray propriété contenant NSLayoutConstraint cas), puis désactiver/supprimer les contraintes à l'aide de l'API sur NSLayoutConstraint ou le PureLayout open-source de la bibliothèque. Vous ne devez désactiver/supprimer que peu de contraintes que possible, car il est gourmand en ressources pour le faire. D'autre part, la modification de laconstant
de toute contrainte est très efficace et encouragé, et vous n'avez pas besoin de supprimer ou de rajouter la contrainte de le faire.NSIBPrototypingLayoutConstraint
s d'être ajouté à "fixer" votre ambigu mises en page...serait utile pour ceux qui veulent l'utiliser xib/storyboard pour configurer les points de vue, mais quelques-uns ou toutes les contraintes réelles dans le code.