106 votes

Problème de mise en page automatique sur iOS7 dans UITableViewCell

Je suis l'aide de l'auto contraintes de mise en forme par programme à la disposition de mon custom UITableView cellules et je suis de définir correctement la taille des cellules en tableView:heightForRowAtIndexPath:

Il fonctionne très bien sur iOS6 et il ne regarde bien dans iOS7 ainsi

MAIS quand je lance l'application sur iOS7, voici le genre de message que je vois dans la console:

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.
2013-10-02 09:56:44.847 Vente-Exclusive[76306: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) 
(
        "<NSLayoutConstraint:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50]   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
        "<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
        "<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
        "<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-|   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>

Et en effet il y a un de la contrainte dans cette liste je ne veux pas :

"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"

et je ne peux pas définir l' translatesAutoresizingMaskIntoConstraints de la propriété de l' contentView PAS => il serait gâcher l'ensemble de la cellule.

44 la valeur par défaut est la hauteur de la cellule, mais j'ai défini mon custom hauteurs de dans la vue de table délégué pourquoi la cellule contentView a cette contrainte? Quelle pourrait en être la cause?

Dans iOS6, il ne se passe rien et tout à l'air très bien sur les deux iOS6 et iOS7.

Mon code est assez grand donc je ne vais pas poster ici, mais n'hésitez pas à demander un pastebin si vous en avez besoin.

Pour spécifier la façon dont je le fais, sur la cellule intialization:

  • Je crée toutes mes étiquettes, boutons, etc
  • J'ai mis leur translatesAutoresizingMaskIntoConstraints propriété
  • - Je les ajouter en tant que sous-vues de l' contentView de la cellule
  • - Je ajouter des contraintes sur l' contentView

Je suis également très intéressé à comprendre pourquoi cela se produit uniquement sur iOS7.

133voto

liamnichols Points 3341

J'ai eu ce problème aussi bien.. Il semble que la contentView du cadre n'a pas mis à jour jusqu' layoutSubviews est appelé cependant le cadre de la cellule est mise à jour plus tôt, laissant le contentView du cadre défini à l' {0, 0, 320, 44} au moment où les contraintes sont évaluées.

Après avoir regardé la contentView plus en détail, Il apparaît que autoresizingMasks ne sont plus ensemble.

Réglage de la autoresizingMask avant de vous contraindre votre point de vue peut résoudre ce problème:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self)
    {
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
        [self loadViews];
        [self constrainViews];
    }
    return self;
}

35voto

KoCMoHaBTa Points 360

Apparemment, il y a quelque chose de mal avec UITableViewCell et UICollectionViewCell sur iOS 7 de l'utilisation d'iOS 8 SDK.

Vous pouvez mettre à jour la cellule contentView lorsque la cellule est réutilisé comme ceci:

Pour Statique UITableViewController:

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }

    //your code goes here

    return cell;
}

#endif
#endif

Depuis Statiques de la Vue de la Table des Contrôleurs sont fragiles et peuvent facilement être rompu si vous en mettre certaines en œuvre de la source de données ou deletegate méthodes - il y a des vérifications qui permettront de s'assurer que ce code ne seront compilés et exécutés sur iOS 7

Il en est de même pour une dynamique de UITableViewController:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        static NSString *cellID = @"CellID";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

        if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
        {
            cell.contentView.frame = cell.bounds;
            cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
        }

        //your code goes here

        return cell;
}

Pour ce cas, nous n'avons pas besoin de la compilation supplément de vérifier, depuis la mise en œuvre de cette méthode est nécessaire.

L'idée est la même pour les deux cas et pour UICollectionViewCell, comme l'a commenté dans ce fil de discussion: question d'un redimensionnement automatique de UICollectionViewCell en Storyboard prototype de cellule (Xcode 6 Bêta 3 du déploiement d'iOS 7)

13voto

Steven Points 31

Comme les cellules sont réutilisées et la hauteur peut varier en fonction du contenu, je pense qu'en général, il serait préférable de définir la priorité de l'espacement de moins que prévu.

Dans votre cas, la UIImageView a un espacement de 15 vers le haut et le bas point de vue a un espacement de 0 vers le bas. Si vous définissez la priorité de ces contraintes à 999 (au lieu de 1000), l'appli ne plante pas, parce que les contraintes ne sont pas nécessaires.

Une fois le layoutSubviews méthode est appelée, la cellule aura la bonne hauteur, et les contraintes peuvent être satisfaits normalement.

9voto

kuchumovn Points 191

Je ne l'ai toujours pas trouvé une bonne solution pour des story-boards... Quelques infos ici aussi: https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188

À partir de ce qu'ils conseils:

self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);

J'ai induite ma solution:

  • cliquez-droit sur la table de montage séquentiel
  • Ouvrir En Tant Que -> Code Source
  • recherchez la chaîne "44", il y
  • ça va être comme

.

<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
        <rect key="frame" x="0.0" y="22" width="320" height="44"/>

.

  • remplacer rowHeight="44" avec rowHeight="9999" et height="44" hauteur="9999"
  • cliquez-droit sur la table de montage séquentiel
  • Ouvrir En Tant Que -> Interface Builder
  • exécutez votre application et vérifiez la sortie

3voto

Vadim Yelagin Points 785

Il suffit d'augmenter la hauteur de cellule par défaut. Le problème est que le contenu de la cellule est supérieur à la taille de cellule par défaut (initiale), violant certaines contraintes de non-négativité jusqu'à ce que la cellule soit redimensionnée à sa taille réelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X