Problème de mise en page automatique avec un en-tête de section UITableView

Je travaille avec un UITableViewController. J'ai un tableau d'objets que l'utilisateur peut supprimer si il va en modifier d'autres. Quand il passe en mode edit, je veux afficher un en-tête qui donne une option pour supprimer tous les éléments. Dans le même temps, il doit afficher une étiquette donnant des informations sur la quantité d'espace utilisé. Je veux ce pour redimensionner automatiquement si l'appareil passe en mode paysage. À partir de ce que je peux dire, j'ai besoin d'utiliser la mise en page automatique pour ce faire.

J'aurais aimé configurer l'en-tête dans un UIView conçu dans le Storyboard, mais le Storyboard permet uniquement de visualiser les contrôleurs, pas vues. Je sais que je pourrais avoir un fichier XIB tenir, mais je préfère éviter que si je le pouvais.

Pour commencer, j'ai remplacé la editing de la propriété, de sorte que je peux redessiner le tableau de la section lorsqu'en mode d'édition.

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    NSIndexSet *set = [NSIndexSet indexSetWithIndex:0];
    [self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
}

- Je utiliser ce code à insérer l'en-tête de section, le cas échéant:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (self.isEditing)
        return [self headerView];
    else
        return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (self.isEditing)
        return [self headerView].frame.size.height;
    else
        return 0;
}

La magie qui se passe dans le - headerView méthode. Elle renvoie une UIView *l'obtenir à partir d'une cache si nécessaire. Il ajoute un bouton et de l'étiquette, puis se met dans la les contraintes. J'ai utilisé ces mêmes contraintes dans le Storyboard et je n'ai pas eu de problèmes.

- (UIView *)headerView
{
if (headerView)
return headerView;
float w = [[UIScreen mainScreen] bounds].size.width;
UIButton *deleteAllButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[deleteAllButton setTitle:@"Delete All" forState:UIControlStateNormal];
CGRect deleteAllButtonFrame = CGRectMake(8.0, 8.0, 30.0, 30);   //The autolayout should resize this.
[deleteAllButton setFrame:deleteAllButtonFrame];
deleteAllButton.translatesAutoresizingMaskIntoConstraints = NO;
[deleteAllButton setContentHuggingPriority:252 forAxis:UILayoutConstraintAxisHorizontal];
[deleteAllButton setContentCompressionResistancePriority:751 forAxis:UILayoutConstraintAxisHorizontal];
CGRect textFrame = CGRectMake(47.0, 8.0, 30.0, 30); //The autolayout should resize this.
UILabel *currSizeText = [[UILabel alloc] initWithFrame:textFrame];
currSizeText.text = @"You have a lot of text here telling you that you have stuff to delete";
currSizeText.translatesAutoresizingMaskIntoConstraints = NO;
currSizeText.adjustsFontSizeToFitWidth = YES;
CGRect headerViewFrame = CGRectMake(0, 0, w, 48);
headerView = [[UIView alloc] initWithFrame:headerViewFrame];
//headerView.autoresizingMask = UIViewAutoresizingNone;//UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//headerView.translatesAutoresizingMaskIntoConstraints = NO;
[headerView addSubview:deleteAllButton];
[headerView addSubview:currSizeText];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(deleteAllButton, currSizeText);
[headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[deleteAllButton]-[currSizeText]-|"
options:0
metrics:nil
views:viewsDictionary]];
[headerView addConstraint:[NSLayoutConstraint constraintWithItem:deleteAllButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:headerView
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];
[headerView addConstraint:[NSLayoutConstraint constraintWithItem:currSizeText
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:headerView
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];
return headerView;
}

Droit maintenant, tout fonctionne à merveille. Le bouton conserve une taille constante (parce que la tendresse et de la résistance à la compression sont plus élevés que le label) et le label va modifier son texte pour l'adapter à l'espace disponible. Il redimensionne quand j'ai faites pivoter l'appareil. Le centrage vertical semble désactivé sur l'étiquette, mais je suis prêt à oublier pour l'instant.

Cependant, lorsque j'ai d'abord configuration de l'en-tête de section, je reçois un ennuyeux de mise en page automatique d'avertissement.

2014-02-07 11:25:19.770 ErikApp[10704:70b] 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) 
(
"<NSLayoutConstraint:0xb9a4ad0 H:|-(NSSpace(20))-[UIButton:0xb99e220]   (Names: '|':UIView:0xb9a4680 )>",
"<NSLayoutConstraint:0xb9a4bf0 H:[UIButton:0xb99e220]-(NSSpace(8))-[UILabel:0xb99f530]>",
"<NSLayoutConstraint:0xb9a4c20 H:[UILabel:0xb99f530]-(NSSpace(20))-|   (Names: '|':UIView:0xb9a4680 )>",
"<NSAutoresizingMaskLayoutConstraint:0xa2d1680 h=--& v=--& H:[UIView:0xb9a4680(0)]>"
)
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xb9a4bf0 H:[UIButton:0xb99e220]-(NSSpace(8))-[UILabel:0xb99f530]>
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.

Ma première pensée a été de changer le retourné UIView propriété translatesAutoresizingMaskIntoConstraints à NO. Quand je fais ça, j'ai eu un crash au lieu d'un avertissement. Pas exactement une amélioration.

2014-02-07 10:49:13.041 ErikApp[10597:70b] *** Assertion failure in -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2903.23/UIView.m:8540
2014-02-07 10:49:13.383 ErikApp[10597:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'

Quelqu'un a une suggestion que faire pour se débarrasser de l'avertissement?

source d'informationauteur Erik Allen