CellForItemAtIndexPath de UICollectionView não está sendo chamado

104

Apenas minha segunda vez usando UICollectionView's e talvez eu tenha mordido mais do que posso mastigar, mas mesmo assim:

Estou implementando um UICollectionView (myCollectionView) que usa UICollectionViewCell personalizado que criei como subclasse. As células subclassed (FullReceiptCell) contêm UITableView's e são do tamanho do viewcontroller. Estou tentando permitir a rolagem horizontal entre FullReceiptCells.

A subclasse UICollectionViewController que contém myCollectionView está sendo enviada para uma pilha de controlador de navegação. Atualmente, myCollectionView loas e rolagem horizontal estão habilitados. No entanto, nenhuma célula é visível. Eu confirmei que

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

foi executado e está retornando um número inteiro maior que 0. Também confirmei que o delegado e a fonte de dados de myCollectionView estão configurados corretamente em IB para a subclasse UICollectionViewController.

O método em que as células devem ser carregadas:

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

não está sendo chamado.

Aqui é onde eu empurro o UICollectionViewController e meu método viewDidLoad dentro desse controlador (NOTA: initWithBill é uma substituição do inicializador normal):

No arquivo ViewControllers .m anterior:

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

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

Alguma pista de por que não está sendo chamado?

IkegawaTaro
fonte
Estou usando o XIB. Não consigo retirar da fila nada em cellForItemsAtIndexPath porque ele nunca é chamado.
IkegawaTaro

Respostas:

135

Para quem tropeçar aqui mais tarde .... o motivo:

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

não estava sendo chamado porque o itemSize para a altura da coleçãoViewFlowLayout era muito grande.

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

Se eu alterar a altura para 410, ele executará cellForItemAtIndexPath.

IkegawaTaro
fonte
Você pode elaborar um pouco mais. O mesmo está acontecendo comigo
user1010819
Acabei de descobrir que você precisa ter cuidado com a collectionViewContentSize também
Dimitar Marinov
49
No caso de você estar usando autolayout - certifique-se de definir uma restrição de altura em collectionView - desperdiçou muitas horas nisso!
bpn
para o recorde de restrição de altura não funcionou para mim .. restrições de centro horizontal funcionaram
Mohamed Emad Hegab
4
Se sua collectionView estiver restrita a topLayoutGuide com AutoLayout e não deve rolar sob NavigationBar, certifique-se de desmarcar Adjust Scroll View Insetsem seu ViewController no Storyboard.
Bruno Galinari
96

No meu caso, foi porque minha classe de layout criou uma subclasse incorreta de em UICollectionViewLayoutvez deUICollectionViewFlowLayout

Esilver
fonte
1
OBRIGADO. Que merda, eu gastei muito tempo nisso.
Rambatino
Esse era o meu problema também! É um pouco contra-intuitivo, então nem me ocorreu. Obrigado por isso!
WendiKidd
O mesmo para mim! é tão fácil ignorar isso! obrigado novamente
arvidurs
Facepalm aqui, obrigado por apontar isso (4 anos atrás).
Milander
Eu estava enfrentando o mesmo problema. Obrigado
Piyush Gupta
31

O cellForItemAtIndexPath não será chamado se você não fornecer as informações de tamanho do conteúdo para a visualização da coleção.

  1. Se você estiver usando o layout de fluxo : Você precisa definir os tamanhos dos itens adequadamente.
  2. Se você tiver um layout personalizado com uma subclasse de UICollectionViewLayout : Certifique-se de estar retornando um tamanho apropriado do método collectionViewContentSize.

No caso do último, você também observará que seu layoutAttributesForElementsRect também não é chamado. O motivo é que você não especificou o tamanho do seu conteúdo e, por padrão, o tamanho será CGSizeZero. Isso basicamente informa ao modo de exibição de coleção que você não tem nenhum conteúdo para pintar, então não se preocupa em solicitar atributos ou células.

Portanto, apenas substitua collectionViewContentSize e forneça um tamanho apropriado lá, isso deve resolver seu problema.

Deepak GM
fonte
1
Por exemplo, para usar o tamanho completo disponível, retorne collectionView.frame.size de collectionViewContentSize (não simplesmente collectionView.contentSize, cujo padrão é 0, 0)
Adam Loving
Obrigado! Essa resposta me ajudou b / c eu tenho um UICollectionViewLayout personalizado. Se eu iniciasse o aplicativo no simulador na orientação paisagem, algumas células não apareciam na visualização inicial. Substituir o tamanho do conteúdo corrigiu esse problema para mim.
Chris Livdahl,
1
Obrigado. No meu caso, o collectionViewContentSizeretornou 0 incorretamente para a largura, é por isso que o cellForItemAtIndexPathnão estava sendo chamado.
izerik
16

Talvez eu esteja apenas esquecendo, mas parece que você está perdendo seu delegado e fonte de dados. Em seu arquivo de cabeçalho, certifique-se de adicionar estes:

<UICollectionViewDelegate, UICollectionViewDataSource>

e em seu método viewDidLoad adicione isto:

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

Além disso, se você estiver carregando-o por meio de um .xib, certifique-se de ter conectado o IBOutlet ao UICollectionView.

Anthony Castelli
fonte
1
Eu não mostrei, mas já tenho o delegado e a fonte de dados anotados no arquivo de cabeçalho. Além disso, conectei o IBOutlet a myCollectionView. O delegado e a fonte de dados para esta visualização da coleção foram configurados para FullReceiptViewController. O estranho é que numberOfItemsInSection (um método de protocolo de fonte de dados) está sendo chamado e retornando um número inteiro maior que 0.
IkegawaTaro
Hmm, quando você inicia o aplicativo, a visualização Coleção mostra ou faz alguma coisa? Parece que há alguns itens se numberOfItemsInSection retornar algo maior que 0.
Anthony Castelli
Obrigado por acompanhar. A visão da coleção mostra ... Posso dizer porque mudei a cor de fundo. Acredito ter encontrado o problema: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; Isso era muito grande. Se eu diminuir a altura para 410, posso fazer com que o método cellForItemAtIndexPath seja chamado.
IkegawaTaro
@AnthonyCastelli Olá, também estou enfrentando o mesmo problema, numberOfItemsInSection sendo chamado no pop para viewController, mas não cellForItemsAtIndexPath. então você entendeu?
Bhavin Kansagara
16

Para uma hierarquia de visão mais complicada, verifique este blog . Isso salvou minha vida!

self.automaticallyAdjustsScrollViewInsets = NO;
Jaybo
fonte
1
Passei muito tempo nisso - e tudo se resumiu a isso. Se estiver usando storyboard ou XIB, olhe para o controlador de visualização pai e desmarque "Ajustar inserções de visualização de rolagem" no Inspetor de atributos, que é ativado por padrão. Eu tentei todas as outras respostas e elas não funcionaram, chegou a hora.
etayluz
15

Se sua classe é uma subclasse de UICollectionviewController e você está criando collectionView programaticamente, use

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

    collectionView?.setCollectionViewLayout(layout, animated: false)
Gurjinder Singh
fonte
Esta é a resposta que resolveu meu problema! O método de substituição func collectionView (_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} não funciona para mim.
Mike
8

Eu estava usando autolayout e, no meu caso , faltava restrição de altura

AamirR
fonte
6

Meu problema era que eu tinha 2 visualizações de coleção na mesma visualização e ambas compartilhavam uma UICollectionViewFlowLayoutinstância computada . Depois de criar instâncias separadas do mesmo layout de fluxo, funcionou bem.

nebyark
fonte
5

No meu caso, o que eu tinha esquecido estupidamente de fazer foi implementar o UICollectionViewDataSourcemétodo do protocolo numberOfItemsInSection, então isso é outra coisa a verificar.

reitor
fonte
4

Além disso, certifique-se de que reloadData não seja chamado enquanto a visualização da coleção está sendo atualizada com animação (inserir, excluir, atualizar ou executarBatchUpdates).

sasha_nec
fonte
4

No meu caso, set collectionView.prefetchingEnabled = NO;resolveu meu problema. Funciona apenas no iOS 10.

6david9
fonte
2
Votei positivamente nessa resposta há algum tempo e hoje ela me ajudou novamente: D Você merece um nobre por essa resposta, cara. Obrigado novamente!
Maciek Czarnik
essa resposta funcionou para mim! Eu gostaria que houvesse uma explicação sobre o porquê incluído nele, porque eu nunca o defini como verdadeiro para começar.
Lance Samaria
3

Isso estava acontecendo comigo quando o item height == 0 fixando que o método cellForItem foi chamado.

Jirune
fonte
3

Dez minutos atrás eu também encontrei esse problema, cometi um erro bobo.

Minha intenção é usar UICollectionViewFlowLayout,

Mas por causa de erros, usei UICollectionViewLayout.

Vincent Sit
fonte
3

No meu caso, alterar o translúcido de UINavigationBar para NÃO resolveu o problema.

chanil
fonte
3

No Xcode 7.0.1, tivemos esse problema quando copiamos um storyboard e o código que o acompanhava de outro projeto. A visualização da coleção tinha um layout de fluxo customizado definido no storyboard. A solução foi:

  • Remova o layout de fluxo em IB
  • Compilar / executar o aplicativo
  • Defina o layout do fluxo de volta

Agora deu certo :)

Bart van Kuik
fonte
2

Certifique-se de numberOfSectionsInCollectionViewretornar um número inteiro positivo também.

Deve haver pelo menos uma seção da coleção.

Eran Goldin
fonte
2

Certifique-se de que - (NSInteger) collectionView: numberOfItemsInSection: está retornando um valor positivo (leitura, maior que zero). Pode ser uma questão de colocar [self.collectionView reloadData]; no manipulador de conclusão.

RT Denver
fonte
2

Esqueci de definir a máscara de redimensionamento automático como falsa na visualização da coleção:

collectionView.translatesAutoresizingMaskIntoConstraints = false
Stritt
fonte
2

Podem ser problemas de layout relacionados. Verifique os avisos de layout do console, se houver.

Erdikanik
fonte
2

No meu caso, a visualização da coleção não estava totalmente visível na visualização pai devido a restrições de layout automático incorretas. Portanto, corrigir as restrições tornou a visualização da coleção totalmente visível e cellForItemAtIndexPath foi chamado.

Khaled Annajar
fonte
2

No storyboard / xib UICollectionView, a propriedade cellSize não DEVE ser {0, 0}

poGUIst
fonte
2

Se estiver usando protocolos de exibição de coleção, você deve conectar os protocolos CollectionViewDataSourcee CollectionViewDelegateao seu ViewController. Pontos de construção de interface

Declan McKenna
fonte
1

O mesmo aconteceu comigo. Eu tinha 2 UICollectionViews e removi uma vez, pois não precisava disso. Depois disso, percebi que CellForItemAtIndexPath não estava sendo chamado, mas sim os outros métodos necessários. Tentei todos os itens acima, mas depois fiz a mágica padrão. Removida a visualização da coleção do storyboard e adicionada novamente. Então começou a funcionar. Não sei por que e não tenho nenhuma explicação, mas talvez alguns problemas de conexão.

Hafeez
fonte
Copiei meu UICollectionView de outro UIViewController no storyboard. Excluí o CollectionView e adicionei novamente para fazê-lo funcionar. Obrigado pela sua resposta.
Drunken Daddy
1

Acabei de resolver esse problema, para uma situação um tanto específica.

No meu caso, eu estava inicializando manualmente o UICollectionViewController em um ViewController pai e, em seguida, adicionando a visualização do UICollectionViewController como uma subvisualização.

Resolvi o problema chamando 'setNeedsLayout' e / ou 'setNeedsDisplay' no collectionView no viewDidAppear do pai:

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

Ao usar, UICollectionViewDelegateFlowLayouttome cuidado com o que esta função retorna. Ambos widthe heightdevem ser maiores que 0. Usei windowcomo referência de quadro, mas devido à janela de hierarquia de visualização complicada estava nilem tempo de execução. Se você precisar ajustar a largura do elemento com base na largura da tela, use UIScreen.main.bounds.

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

No meu caso, tive o collectionViewin a UIStackViewwith alignment = .center. Portanto, o collectionViewnão tinha largura. Ao definir o stackView.alignmentpara .filltudo estava bem.

Nico S.
fonte
0

Para mim, eu atualizo a altura de self.view (a superview do collectionView) por meio de autolayout e DEVO chamar layoutIfNeededdepois disso.

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

No meu caso, tive que ajustar o tamanho estimado do conteúdo. o tamanho do conteúdo não fazia isso.

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

Eu estava tendo um problema semelhante. Em vez disso, cellForItemAtIndexPathfoi chamado quando o número de itens era> 1, mas não quando havia apenas um único item. Tentei muitas das soluções propostas aqui e, semelhantes a muitas, descobri que tinha a ver com dimensionamento de itens. Para mim, a solução foi alterar o tamanho estimado UICollectionViewdo automático para personalizado .

Defina o tamanho estimado para personalizado

Wouter
fonte
-1

Eu perdi um pouco de tempo com esse problema vindo de um controlador de exibição CollectionView em um Contained carregado de um storyboard. Acabei simplesmente excluindo o controlador de visualização contido e recriando-o no storyboard, e isso pareceu eliminar o problema. Meu palpite é que ocorreu algum tipo de corrupção do storyboard.

Wfbarksdale
fonte