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é?


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.


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


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.


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.


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;

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)

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


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é.


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.


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).


4

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


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.


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.


3

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


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é :)


2

Assurez-vous que numberOfSectionsInCollectionViewrenvoie également un entier positif.

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


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.


2

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

collectionView.translatesAutoresizingMaskIntoConstraints = false

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.


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é.


2

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


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


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.


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];
}

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 {}

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.


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];

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)

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é


-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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.