115 votes

"Mise en page automatique toujours requise après l'exécution de -layoutSubviews" avec la sous-classe UITableViewCell

En utilisant XCode 4.5 et iOS 6, je suis le développement d'une application avec une simple vue de table personnalisée avec des cellules. J'ai fait ça des centaines de fois dans iOS 5 et au-dessous, mais pour une raison quelconque, la nouvelle mise en page automatique du système est de me donner beaucoup de mal.

J'ai installé ma table de la vue et d'un prototype de cellule de l'IB, ajouté des sous-vues et câblé comme IBOutlets puis l'installation de mon délégué et de la source de données. Mais maintenant, chaque fois que la première cellule est extraite de l' cellForRowAtIndexPath, j'obtiens l'erreur suivante:

*** L'échec d'Assertion dans -[ShopCell layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2372/UIView.m:5776

*** Fin de l'app en raison de uncaught exception 'NSInternalInconsistencyException', la raison: 'Mise en page Automatique encore nécessaires après l'exécution d'-layoutSubviews. ShopCell de la mise en œuvre de layoutSubviews doit appeler super.'

Je n'ai pas mis en œuvre un -layoutSubviews méthode dans mon sous-classé cellule (ShopCell), et même quand j'essaie de le faire et ajouter le super appeler comme il le suggère, je reçois toujours le même message d'erreur. Si je retire le sous-vues de la cellule de l'IB, et de le changer pour un standard de UITableViewCell, tout fonctionne comme prévu, même si bien sûr je suis à gauche avec pas de données dans mes cellules.

Je suis presque certain qu'il ya quelque chose de simple, je suis absent, mais ne peut pas trouver de la documentation ou des guides pour vous proposer ce que j'ai fait de mal. Toute aide serait appréciée.

Edit: Juste essayé de le changer pour un UITableViewCell de l'IB et en laissant tous les sous-vues en place, toujours la même erreur.

57voto

Malaxeur Points 4277

J'ai rencontré le même problème lors de l'ajout manuel de contraintes dans le code. Dans le code, j'ai fait la suivante:

{
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    [self addSubview:someView];
    [self addSubview:someOtherView];
    [self addConstraint:...];
}

Hypothèse

À partir de ce que je peux dire, le problème est que lorsque vous désactivez translatesAutoresizingMaskIntoConstraints, UITableViewCell commence à utiliser la Mise en page Automatique et naturellement échoue parce que l'implémentation sous-jacente de l' layoutSublayersForLayer n'appelle pas super. Quelqu'un avec une Trémie ou un autre outil peut confirmer cela. Puisque vous êtes à l'aide de l'IB, vous vous demandez probablement pourquoi est-ce un problème... et c'est parce que l'utilisation de l'IB désactive automatiquement translatesAutoresizingMaskIntoConstraints pour les vues qu'il ajoute des contraintes (il va automatiquement ajouter une largeur et une hauteur de contrainte à leur place).

Solution

Ma solution a été de passer le tout à l' contentView.

{
   [self.contentView addSubview:someView];
   [self.contentView addSubview:someOtherView];
   [self.contentView addConstraint:...];
}

Je ne suis pas sûr à 100% si cela va fonctionner dans Interface Builder, mais si vous pousser hors tout de votre cellule (en supposant que vous avez quelque chose directement sur lui), alors il devrait fonctionner. Espérons que cela vous aide!

53voto

Carl Lindberg Points 976

Apparemment, UITableViewCell de layoutSubviews mise en œuvre n'appelle pas super, ce qui est un problème de mise en page automatique. Je serais curieux de voir si la chute la catégorie ci-dessous dans les projets résout des choses. Il a aidé dans un projet de test.

#import <objc/runtime.h>
#import <objc/message.h>

@implementation UITableViewCell (FixUITableViewCellAutolayoutIHope)

+ (void)load
{
    Method existing = class_getInstanceMethod(self, @selector(layoutSubviews));
    Method new = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));

    method_exchangeImplementations(existing, new);
}

- (void)_autolayout_replacementLayoutSubviews
{
    [super layoutSubviews];
    [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
    [super layoutSubviews];
}

@end

J'ajouterais que le problème s'est présenté pour moi lors de l'utilisation d'un backgroundView sur la cellule du tableau, qui est ajouté une sous-vue de la cellule (alors que la plupart des sous-vues doit être ajouté à la table de la cellule contentView, qui doivent généralement travailler mieux).

Remarque: Il apparaît que ce bug est corrigé dans iOS7; j'ai été en mesure de supprimer ce code, ou au moins d'y ajouter un moment de l'exécution, de sorte qu'il n'a effectué que si en cours d'exécution sur iOS6.

33voto

Arnaud Points 459

J'ai eu le même bug pour quelques mois. Mais j'ai trouvé quel était le problème.

Lorsque je crée un IB, un fichier d' UIView a déjà été ajouté. Si vous utilisez ce point de vue, l'application ne plante pas lors de la mise en page automatique est désactivé (mais il y a d'autres questions). Lorsque vous utilisez la mise en page automatique, vous devez sélectionner le bouton droit de la vue dans la Bibliothèque d'Objet : UITableViewCell.

En fait, vous devriez toujours utiliser ce point parce que tous les sous-vues sont ajoutés à l' contentView de la UITableViewCell.

C'est tout. Tout sera bien.

15voto

Keller Points 6797

Avait le même problème dans iOS 7 (iOS 8 semble corriger). La solution pour moi était d'appeler [self.view layoutIfNeeded] à la fin de ma méthode viewDidLayoutSubviews .

14voto

Trunal Bhanse Points 623

J'ai eu le même problème. Le problème était dans la façon dont je créais la cellule Xib. J'ai créé un fichier Xib comme d'habitude et j'ai simplement changé le type de "UIView" par défaut en ma classe UITableViewCell personnalisée. La méthode correcte consiste d'abord à supprimer la vue par défaut, puis à faire glisser l'objet cellule de vue de table sur le xib. Plus de détails ici: http://allplayers.github.io/blog/2012/11/18/Custom-UITableViewCell-With-NIB/

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