CellForItemAtIndexPath de UICollectionView n'est pas appelé

104

Ce n'est que ma deuxième fois que j'utilise UICollectionView et j'ai peut-être mordu plus que je ne peux mâcher, mais néanmoins:

J'implémente un UICollectionView (myCollectionView) qui utilise des UICollectionViewCell personnalisés que j'ai sous-classés. Les cellules sous-classées (FullReceiptCell) contiennent UITableView et ont la taille du viewcontroller. J'essaye de permettre le défilement horizontal entre les FullReceiptCells.

Le UICollectionViewController sous-classé qui contient myCollectionView est poussé sur une pile de contrôleurs de navigation. Actuellement, myCollectionView loas et le défilement horizontal sont activés. Cependant, aucune cellule n'est visible. J'ai confirmé que

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

a exécuté et renvoie un entier supérieur à 0. J'ai également confirmé que le délégué et la source de données de myCollectionView sont correctement définis dans IB pour le UICollectionViewController sous-classé.

La méthode dans laquelle les cellules doivent être chargées:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

n'est pas appelé.

Voici où je pousse UICollectionViewController et ma méthode viewDidLoad dans ce contrôleur (REMARQUE: initWithBill est un remplacement de l'initialiseur normal):

Dans le fichier .m ViewControllers précédent:

FullReceiptViewController *test = [[FullReceiptViewController alloc] initWithBill:currentBill];
test.title = @"Review";
[self.navigationController pushViewController:test animated:YES];

Dans FullReceiptViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self.myCollectionView registerClass:[FullReceiptCell class] forCellWithReuseIdentifier:@"FullReceiptCellIdentifier"];
    self.myCollectionView.pagingEnabled = YES;
    // Setup flowlayout

    self.myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
    [self.myCollectionViewFlowLayout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    [self.myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    self.myCollectionViewFlowLayout.minimumLineSpacing = 0;
    self.myCollectionViewFlowLayout.minimumInteritemSpacing = 0;
    [self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
    //testing to see if the collection view is loading
    self.myCollectionView.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];

Un indice quant à la raison pour laquelle il n'est pas appelé?

IkegawaTaro
la source
J'utilise XIB. Je ne peux rien retirer de la file d'attente dans cellForItemsAtIndexPath car il n'est jamais appelé.
IkegawaTaro

Réponses:

135

Pour ceux qui trébucheront ici plus tard ... la raison:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

n'a pas été appelé parce que la hauteur de itemSize de la collectionViewFlowLayout était trop grande.

[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];

Si je change la hauteur à 410, il exécutera cellForItemAtIndexPath.

IkegawaTaro
la source
Pouvez-vous élaborer un peu plus. La même chose se passe pour moi
user1010819
Je viens de découvrir que vous devez également faire attention avec collectionViewContentSize
Dimitar Marinov
49
Dans le cas où vous utilisez la mise en page automatique - assurez-vous de définir une contrainte de hauteur sur la collectionView - vous avez perdu de nombreuses heures à ce sujet!
bpn le
pour la contrainte de hauteur record n'a pas fonctionné pour moi .. les contraintes horizontales au centre ont fait l'affaire
Mohamed Emad Hegab
4
Si votre collectionView est contrainte à topLayoutGuide avec AutoLayout, et n'est pas censée défiler sous NavigationBar, assurez-vous de décocher Adjust Scroll View Insetsvotre ViewController sur Storyboard.
Bruno Galinari
96

Dans mon cas, c'était parce que ma classe de mise en page était incorrectement sous-classée de UICollectionViewLayoutau lieu deUICollectionViewFlowLayout

argent
la source
1
JE VOUS REMERCIE. Embrasse-moi, j'ai passé des siècles là-dessus.
Rambatino
C'était aussi mon problème! C'est un peu contre-intuitif, donc cela ne m'est même pas venu à l'esprit. Merci pour cela!
WendiKidd
Pareil pour moi! c'est tellement facile d'oublier ça! merci encore
arvidurs
Facepalm ici, merci de le signaler (il y a 4 ans).
Milander
J'étais confronté au même problème. Merci
Piyush Gupta
31

Le cellForItemAtIndexPath ne sera pas appelé si vous ne fournissez pas les informations de taille de contenu à la vue de collection.

  1. Si vous utilisez la mise en page Flow : vous devez définir correctement les tailles des éléments.
  2. Si vous avez une disposition personnalisée sous-classée à partir de UICollectionViewLayout : assurez -vous de renvoyer une taille appropriée à partir de la méthode collectionViewContentSize.

Dans ce dernier cas, vous remarquerez également que votre layoutAttributesForElementsRect n'est pas non plus appelé. La raison est que vous n'avez pas spécifié la taille de votre contenu et par défaut, la taille sera CGSizeZero. Cela indique essentiellement à la vue de la collection que vous n'avez aucun contenu à peindre, donc cela ne prend pas la peine de vous demander des attributs ou des cellules.

Donc, remplacez simplement collectionViewContentSize et fournissez une taille appropriée, cela devrait résoudre votre problème.

Deepak GM
la source
1
Par exemple, pour utiliser la taille totale disponible, renvoyez collectionView.frame.size à partir de collectionViewContentSize (pas simplement collectionView.contentSize qui vaut par défaut 0, 0)
Adam Loving
Merci! Cette réponse m'a aidé b / c j'ai un UICollectionViewLayout personnalisé. Si j'ai démarré l'application dans le simulateur en orientation paysage, certaines cellules n'apparaissaient pas dans la vue initiale. Le remplacement de la taille du contenu a résolu ce problème pour moi.
Chris Livdahl
1
Je vous remercie. Dans mon cas, le collectionViewContentSize0 renvoyé par erreur pour la largeur, c'est pourquoi le cellForItemAtIndexPathn'a pas été appelé.
izerik
16

Peut-être que je l'ignore, mais il semble que votre délégué et votre source de données vous manquent. Dans votre fichier d'en-tête, assurez-vous d'avoir ajouté ces éléments:

<UICollectionViewDelegate, UICollectionViewDataSource>

et dans votre méthode viewDidLoad, ajoutez ceci:

self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;

De plus, si vous le chargez via un .xib, assurez-vous que vous avez connecté l'IBOutlet à UICollectionView.

Anthony Castelli
la source
1
Je ne l'ai pas montré mais j'ai déjà noté le délégué et la source de données dans le fichier d'en-tête. De plus, j'ai câblé l'IBOutlet à myCollectionView. Le délégué et la source de données pour cette vue de collection ont été définis sur FullReceiptViewController. La chose étrange est que numberOfItemsInSection (une méthode de protocole de source de données) est appelée et renvoie un entier supérieur à 0.
IkegawaTaro
Hmm, lorsque vous lancez l'application, la vue Collection s'affiche-t-elle ou fait quelque chose? On dirait qu'il contient des éléments si numberOfItemsInSection renvoie quelque chose de supérieur à 0.
Anthony Castelli
Merci pour le suivi. La collectionview montre ... Je peux dire parce que j'ai changé la couleur de fond. Je crois avoir trouvé le problème: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; C'était trop gros. Si je diminue la hauteur à 410, je peux appeler la méthode cellForItemAtIndexPath.
IkegawaTaro
@AnthonyCastelli Bonjour, je suis également confronté au même problème, numberOfItemsInSection étant appelé sur pop pour viewController mais pas cellForItemsAtIndexPath. alors avez-vous l'indice?
Bhavin Kansagara
16

Pour une hiérarchie des vues plus compliquée, veuillez consulter ce blog . Cela m'a sauvé la vie!

self.automaticallyAdjustsScrollViewInsets = NO;
Jaybo
la source
1
J'ai passé tellement de temps là-dessus - et tout se résume à cela. Si vous utilisez un storyboard ou XIB, regardez le contrôleur de vue parent et désélectionnez "Ajuster les encarts de vue de défilement" dans l'inspecteur d'attributs qui est activé par défaut. J'ai essayé toutes les autres réponses et elles n'ont pas fonctionné, cela se résumait à ceci.
etayluz
15

Si votre classe est une sous-classe de UICollectionviewController et que vous créez collectionView par programme, utilisez

let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .Vertical
    layout.itemSize = CGSizeMake(50, 50)

    collectionView?.setCollectionViewLayout(layout, animated: false)
Gurjinder Singh
la source
C'est la réponse a résolu mon problème! La méthode de substitution func collectionView (_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} ne fonctionne pas pour moi.
Mike
8

J'utilisais la mise en page automatique et dans mon cas, la contrainte de hauteur était manquante

AamirR
la source
6

Mon problème était que j'avais 2 vues de collection dans la même vue, et les deux partageaient une UICollectionViewFlowLayoutinstance calculée . Une fois que j'ai créé des instances séparées de la même disposition de flux, cela a bien fonctionné.

nebyark
la source
5

Dans mon cas, ce que j'avais bêtement oublié de faire était d'implémenter la UICollectionViewDataSourceméthode du protocole numberOfItemsInSection, donc c'est une autre chose à vérifier.

doyen
la source
4

Assurez-vous également que reloadData n'est pas appelé pendant la mise à jour de la vue de collection avec une animation (insérer, supprimer, mettre à jour ou effectuerBatchUpdates).

sasha_nec
la source
4

Dans mon cas, set a collectionView.prefetchingEnabled = NO;résolu mon problème. Fonctionne uniquement sur iOS 10.

6david9
la source
2
J'ai voté pour cette réponse il y a quelque temps et aujourd'hui, cela m'a aidé à nouveau: D Vous méritez un Noble pour cette réponse. Merci encore!
Maciek Czarnik le
cette réponse a fonctionné pour moi! J'aurais aimé qu'il y ait une explication quant à la raison pour laquelle il est inclus, car je ne l'avais jamais mis à vrai pour commencer.
Lance Samaria
3

Cela se passait pour moi lorsque la hauteur de l'élément == 0 en corrigeant cette méthode cellForItem a été appelée.

Jirune
la source
3

Il y a dix minutes, j'ai également rencontré ce problème, j'ai fait une erreur stupide.

Mon intention est d'utiliser UICollectionViewFlowLayout,

Mais à cause d'erreurs, j'ai utilisé UICollectionViewLayout.

Vincent Sit
la source
3

Dans mon cas, changer le translucide de UINavigationBar en NO a résolu le problème.

chanil
la source
3

Dans Xcode 7.0.1, nous avons eu ce problème lorsque nous avons copié un storyboard et le code associé d'un autre projet. La vue de collection avait une disposition de flux personnalisée définie dans le storyboard. La solution était de:

  • Supprimer la disposition de flux dans IB
  • Compilez / exécutez l'application
  • Rétablir la disposition du flux

Maintenant ça a marché :)

Bart van Kuik
la source
2

Assurez-vous que numberOfSectionsInCollectionViewrenvoie également un entier positif.

Il doit y avoir au moins une section dans la collection.

Eran Goldin
la source
2

Assurez-vous que - (NSInteger) collectionView: numberOfItemsInSection: renvoie une valeur positive (lecture, supérieure à zéro). Il peut s'agir de placer [self.collectionView reloadData]; dans le gestionnaire de complétion.

RT Denver
la source
2

J'ai oublié de définir le masque de redimensionnement automatique sur false dans la vue de collection:

collectionView.translatesAutoresizingMaskIntoConstraints = false
Stritt
la source
2

Il peut s'agir de problèmes de mise en page réalisés. Vérifiez les avertissements de mise en page de la console, le cas échéant.

Erdikanik
la source
2

Dans mon cas, la vue de collection n'était pas entièrement visible dans sa vue parente en raison de mauvaises contraintes de mise en page automatique. Ainsi, la correction des contraintes rendait la vue de la collection entièrement visible et cellForItemAtIndexPath a été appelé.

Khaled Annajar
la source
2

Dans le storyboard / xib UICollectionView, la propriété cellSize DOIT ne pas être {0, 0}

poGUIst
la source
2

Si vous utilisez des protocoles de vue de collection, vous devez connecter les protocoles CollectionViewDataSourceet CollectionViewDelegateà votre ViewController. Prises de création d'interface

Declan McKenna
la source
1

La même chose m'est arrivée. J'avais 2 UICollectionViews et j'ai supprimé une fois car je n'en avais pas besoin. Après cela, j'ai réalisé que le CellForItemAtIndexPath n'était pas appelé mais les autres méthodes requises. J'ai essayé tout ce qui précède mais j'ai ensuite fait la magie standard. Suppression de la vue de collection du storyboard et ajout à nouveau. Ensuite, cela a commencé à fonctionner. Je ne sais pas pourquoi et je n'ai aucune explication, mais peut-être des problèmes de connexion.

Hafeez
la source
J'ai copié mon UICollectionView à partir d'un autre UIViewController dans le storyboard. J'ai supprimé le CollectionView et ajouté à nouveau pour le faire fonctionner. Merci pour votre réponse.
Drunken Daddy le
1

Je viens de résoudre ce problème, pour une situation un peu spécifique.

Dans mon cas, j'initialisais manuellement l'UICollectionViewController dans un ViewController parent, puis j'ajoutais la vue UICollectionViewController en tant que sous-vue.

J'ai résolu le problème en appelant 'setNeedsLayout' et / ou 'setNeedsDisplay' sur la collectionView dans le viewDidAppear du parent:

- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   [_collection.view setNeedsLayout];
   [_collection.view setNeedsDisplay];
}
Tim
la source
1

Lorsque vous utilisez, UICollectionViewDelegateFlowLayoutfaites attention à ce que cette fonction renvoie. Les deux widthet heightdoivent être supérieurs à 0. J'ai utilisé windowcomme référence de cadre, mais en raison de la complexité de la fenêtre de hiérarchie des vues, c'était nilau moment de l'exécution. Si vous avez besoin d'ajuster la largeur de l'élément en fonction de l'utilisation de la largeur de l'écran UIScreen.main.bounds.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
           UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {}
inokey
la source
1

Dans mon cas, j'ai eu le collectionViewdans un UIStackViewavec alignment = .center. Donc, le collectionViewn'avait pas de largeur. Lors de la mise stackView.alignmentà .filltout allait bien.

Nico S.
la source
0

Pour moi, je mets à jour la hauteur de self.view (le superview de collectionView) via la mise en page automatique, et DOIT appeler layoutIfNeededaprès cela.

[self.view mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(@(height));
}];
[self.view layoutIfNeeded];
M. Ming
la source
0

Dans mon cas, j'ai dû ajuster la taille estimée du contenu. la taille du contenu ne l'a pas fait.

  let layout = collectionVC.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: 100, height: 100)
    layout.estimatedItemSize = CGSize(width: 100, height: 100)
tobi
la source
0

J'avais un problème similaire. Mais à la place, il cellForItemAtIndexPathétait appelé lorsque le nombre d'éléments était> 1, mais pas lorsqu'il n'y avait qu'un seul élément. J'ai essayé de nombreuses solutions proposées ici et, comme beaucoup d'autres, j'ai trouvé que cela avait à voir avec le dimensionnement des articles. Pour moi, la solution était de changer la taille estimée de la UICollectionViewde Automatique à Personnalisée .

Définir la taille estimée sur Personnalisé

Wouter
la source
-1

J'ai perdu un peu de temps avec ce problème à venir avec un CollectionView dans un contrôleur de vue contenue chargé à partir d'un storyboard. J'ai fini par simplement supprimer le contrôleur de vue contenu et le recréer dans le storyboard, ce qui a semblé résoudre le problème. Je suppose qu'il y avait une sorte de corruption de storyboard qui avait eu lieu.

wfbarksdale
la source