0

j'ai commencé à utiliser autolayout et les contraintes programatically, mais je ne comprends pas pourquoi je reçois l'avertissement suivantne peut satisfaire les contraintes - Format du langage Visual

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) 
(
    "<NSLayoutConstraint:0x7fbbd142ead0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fbbd162ec70(44)]>", 
    "<NSLayoutConstraint:0x7fbbd1431740 V:|-(20)-[UILabel:0x7fbbd174e520'Liked'] (Names: '|':UITableViewCellContentView:0x7fbbd162ec70)>", 
    "<NSLayoutConstraint:0x7fbbd1431790 V:[UILabel:0x7fbbd174e520'Liked']-(NSSpace(8))-[UILabel:0x7fbbd174e7e0's']>", 
    "<NSLayoutConstraint:0x7fbbd14317e0 V:[UILabel:0x7fbbd174e7e0's']-(20)-| (Names: '|':UITableViewCellContentView:0x7fbbd162ec70)>" 
) 

Je sais que la ligne de code qui est à l'origine de l'erreur est:

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 

mais je ne comprends pas pourquoi la contrainte ne peut pas être satisfaite. Cela peut être une question stupide, mais je suis nouveau à autolayout et le sujet est confus, à cause de la documentation incomplète. J'ai essayé différentes variantes et solutions mais je n'ai pas trouvé la bonne. Qu'est-ce que je rate? Je colle également le code de ma cellule de vue de table personnalisée pour une inspection plus détaillée.

@implementation NotificationCell 
@synthesize nameLbl,notificationLbl,textLabel,timeLbl,profileImgView,notificationImgView,clockImgView,didSetupConstraints; 
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 


     nameLbl = [[UILabel alloc]init]; 
     [nameLbl setTextColor:[UIColor blueColor]]; 
     nameLbl.translatesAutoresizingMaskIntoConstraints = NO; 
     [nameLbl setTextAlignment:NSTextAlignmentLeft]; 
     [nameLbl setNumberOfLines:1]; 

     [nameLbl setBackgroundColor:[UIColor redColor]]; 
     [self.contentView addSubview:nameLbl]; 

     notificationLbl = [[UILabel alloc]init]; 
     [notificationLbl setTextColor:[UIColor lightGrayColor]]; 
     notificationLbl.translatesAutoresizingMaskIntoConstraints = NO; 
     [notificationLbl setTextAlignment:NSTextAlignmentLeft]; 
     [notificationLbl setNumberOfLines:1]; 
     [self.contentView addSubview:notificationLbl]; 

     textLabel = [[UILabel alloc]init]; 
     [textLabel setTextColor:[UIColor blueColor]]; 
     textLabel.translatesAutoresizingMaskIntoConstraints = NO; 
     [textLabel setTextAlignment:NSTextAlignmentLeft]; 
     [textLabel setNumberOfLines:0]; 
     [textLabel setBackgroundColor:[UIColor grayColor]]; 
     [self.contentView addSubview:textLabel]; 

     timeLbl = [[UILabel alloc]init]; 
     [timeLbl setTextColor:[UIColor grayColor]]; 
     timeLbl.translatesAutoresizingMaskIntoConstraints = NO; 
     [timeLbl setTextAlignment:NSTextAlignmentLeft]; 
     [timeLbl setNumberOfLines:1]; 

     [self.contentView addSubview:timeLbl]; 

     profileImgView = [[UIImageView alloc]init]; 
     [profileImgView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [profileImgView setBackgroundColor:[UIColor redColor]]; 
     [profileImgView.layer setCornerRadius:20]; 
     [profileImgView.layer setMasksToBounds:YES]; 
     [self.contentView addSubview:profileImgView]; 

     clockImgView = [[UIImageView alloc]init]; 
     [clockImgView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [clockImgView setBackgroundColor:[UIColor blueColor]]; 
     [clockImgView.layer setCornerRadius:10]; 
     [clockImgView.layer setMasksToBounds:YES]; 
     [self.contentView addSubview:clockImgView]; 

     notificationImgView = [[UIImageView alloc]init]; 
     [notificationImgView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [notificationImgView setBackgroundColor:[UIColor purpleColor]]; 
     [notificationImgView.layer setCornerRadius:10]; 
     [notificationImgView.layer setMasksToBounds:YES]; 
     [self.contentView addSubview:notificationImgView]; 

     /*[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_headerView(==80)]-0-[_tableView]-|" 
                      options:NSLayoutFormatDirectionLeadingToTrailing 
                      metrics:nil 
                      views:elementsDict]];*/ 



    } 
    return self; 
} 
-(void)updateConstraints{ 
    if (self.didSetupConstraints == NO) { 

     NSDictionary *views = NSDictionaryOfVariableBindings(nameLbl,notificationLbl,notificationImgView,textLabel,timeLbl,profileImgView,clockImgView); 
     NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[profileImgView(40)]-10-[textLabel]-[clockImgView(20)]-[timeLbl(20)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[profileImgView]-10-[nameLbl]-[clockImgView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[profileImgView]-10-[notificationImgView(20)]-[notificationLbl]-[clockImgView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[notificationImgView(20)]-[textLabel]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[profileImgView(40)]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[clockImgView(20)]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[timeLbl]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]; 
     [self.contentView addConstraints:constraints]; 
     self.didSetupConstraints = YES; 
    } 
    [super updateConstraints]; 
} 
- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    [self.contentView setNeedsLayout]; 
    [self.contentView layoutIfNeeded]; 

    self.textLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.textLabel.frame); 
} 
+0

Quelles versions iOS devez-vous prendre en charge? (Ce comportement a changé un peu dans iOS 8.) Quelle version iOS était en cours d'exécution lorsque vous avez reçu les avertissements ci-dessus? En outre, je suppose que vous n'utilisez pas de prototypes de cellules, mais que vous avez plutôt un 'cellForRowAtIndexPath' qui l'instancie manuellement? Peut-être partager comment la cellule est créée, car le comportement diffère en fonction de la façon dont la cellule a été créée. – Rob

+0

J'ai une cellule prototype mais je la crée par programmation comme vous pouvez le voir dans le code ci-dessus, alors quel est votre point de vue? Je suis en train de tester sur iOS 8. – axel

+0

Si vous utilisez un prototype de cellule, il instancie la cellule avec 'initWithCoder', pas' initWithStyle', ce qui explique pourquoi j'ai posé cette question. J'ai seulement posé des questions sur le prototype parce que (en particulier iOS 7), le comportement dépend fortement de la façon dont vous avez créé la cellule, et vous ne l'avez pas partagé avec nous. Sur un sujet distinct, je suis surpris que vous n'ayez pas appelé 'setNeedsUpdateConstraints' après avoir ajouté les sous-vues (c'est ce que l'on appelle généralement pour que l'OS appelle' updateConstraints' pour vous, mais comment cette méthode est appelée). – Rob

Répondre

0

Cela se produit parce que la hauteur de votre cellule est de 44 points, mais vous avez placés verticalement les étiquettes, où seuls les espaces sont un espacement d'espacement 20 + std + std + 20, qui est nettement plus que 44, et encore est la hauteur de l'étiquette, que vous devez prendre en compte: V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|. Donc vous devriez augmenter la taille de votre cellule.

+0

La hauteur de ma cellule est dynamique, ce qui signifie qu'elle dépend du nombre de caractères ajoutés dans l'une de mes étiquettes. – axel

+0

Vous devez faire quelque chose de mal là-bas. Regardez cette contrainte: 'V: [UITableViewCellContentView: 0x7fbbd162ec70 (44)]'. Comment définissez-vous la hauteur de la cellule? Pourriez-vous partager le code? Si par dynamic, vous vouliez dire que la hauteur de la cellule est calculée par les contraintes qui sont à l'intérieur, ce n'est pas comme ça que les contraintes fonctionnent. Cela n'a aucun effet sur la vue d'ensemble, donc le code que vous avez partagé ne changera pas la hauteur de votre cellule. – Levi

+0

Je règle le 'estiméRowHeight' avec' [_tableView setEstimatedRowHeight: 100.0f]; 'et rowHeight' avec' [_tableView setRowHeight: UITableViewAutomaticDimension]; '. – axel

1

Quelques pensées:

  1. Assurez-vous que vous ne définissez explicitement la propriété rowHeight sur la vue de la table, ni la mise en œuvre tableView:heightForRowAtIndexPath: dans votre UITableViewDelegate. L'une d'entre elles établira des contraintes conflictuelles avec une cellule qui effectue des calculs de hauteur basés sur des contraintes.

  2. Bien que je ne l'ai pas trouvé nécessaire, « Luc dit » (en WWDC 2014 vidéo What's New in Table and Collection Views) il faut mettre estimatedRowHeight pour la vue de la table (par exemple dans viewDidLoad) lors de l'utilisation contrainte générée la hauteur des lignes.

    self.tableView.estimatedRowHeight = 44; 
    
  3. J'ai pas jugé nécessaire de le faire, mais dans le même WWDC 2014 vidéo, le présentateur, Luke, devenais erreurs de contraintes étranges semblables à la vôtre jusqu'à ce qu'il a ajouté la ligne suivante à son code :

    self.tableView.rowHeight = UITableViewAutomaticDimension; 
    

    il a dit que ce ne serait pas nécessaire dans la prochaine graine, mais dans sa démonstration, il était nécessaire.

  4. J'ai remarqué que vous pouvez toujours recevoir l'erreur de contraintes insatisfaisantes (même si vous avez fait ce qui précède et que toutes vos contraintes sont correctes). J'ai trouvé que si vous changez un de vos contraintes verticales de la cellule d'avoir une priorité moins de 1000, il semble résoudre ce problème (et la cellule semble être correctement formaté.

Remarque, ce comportement de automatiquement les hauteurs de ligne calculées diffèrent dans iOS 7. Mais dans iOS 8, ce qui précède devrait le faire.Si vous avez encore des problèmes, créez un projet de test qui manifeste le problème et chargez-le quelque part où nous pouvons le regarder

+0

J'ai essayé tous les ci-dessus sans succès. Je place le estiméRowHeight à 100.0 sans succès, il est toujours 44. Le rowHeight est également défini sur UITableViewAutomaticDimension. Tout est affiché correctement sur iOS 8 et iOS 7.1 mais je reçois toujours ces avertissements pour une raison quelconque ... Peut-être que je devrais vraiment télécharger mon projet de test quelque part afin que vous puissiez l'examiner. – axel

+0

Je l'ai corrigé en ajoutant 'self.frame = CGRectMake (0, 0, self.frame.size.width, 100.0f); self.contentView.frame = CGRectMake (0, 0, self.contentView.frame.size.width, 100.0f); 'dans la méthode' updateConstraints' ... – axel

0

Vous devez définir self.tableView.rowHeight = UITableViewAutomaticDimension; Il fera dynamiquement de la hauteur tableViewCell

Vous devrez peut-être également définir des contraintes de hauteur pour étiqueter plus grand que de façon égale, de sorte que si ce n'est pas le cas, sa hauteur peut être 0.

0

Quelques suggestions de mon expérience avec des hauteurs de cellules dynamiques:

En premier lieu, ne remplacent pas la méthode updateConstraints dans le NotificationCell. Ajoutez à la place vos contraintes dans la méthode init, après avoir ajouté toutes les vues secondaires au contentView.

Ensuite, changer votre implémentation de heightForRow

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath { 
     NotificationCell *cell = [[NotificationCell alloc] init]; 

     // Do all your configuration here 
     cell.nameLabel.text = [_names objectAtIndex:indexPath.row]; 
     // Add all the rest too ... 

     CGFloat cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingSizeCompressedSize].height; 
     // Add a breakpoint here to see if your constraints are right and if the height is calculated correctly 

     return height + 1; 
} 

Si vos étiquettes ne sont pas multiligne, même sans mettre le texte, doit être calculé correctement la hauteur. Toutefois, s'ils peuvent s'étendre sur plusieurs lignes, vous devez définir la valeur du texte dans la méthode heightForRow.

Espérons que cela résoudra votre problème.