UICollectionView cellForItemAtIndexPath nie jest wywoływana

104

Dopiero po raz drugi używam UICollectionView i być może odgryzłem więcej, niż jestem w stanie przeżuć, ale mimo to:

Implementuję UICollectionView (myCollectionView), który używa niestandardowych UICollectionViewCell, które mam podklasę. Komórki podklasy (FullReceiptCell) zawierają UITableView i mają rozmiar kontrolera widoku. Próbuję zezwolić na przewijanie w poziomie między FullReceiptCells.

Podklasa UICollectionViewController, która zawiera myCollectionView, jest wypychana do stosu kontrolera nawigacji. Obecnie Loas myCollectionView i przewijanie w poziomie są włączone. Jednak żadne komórki nie są widoczne. Potwierdziłem to

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

został uruchomiony i zwraca liczbę całkowitą większą niż 0. Potwierdziłem również, że delegat myCollectionView i źródło danych są prawidłowo ustawione w IB do podklasy UICollectionViewController.

Sposób ładowania komórek:

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

nie jest wezwany.

Oto miejsce, w którym wypycham UICollectionViewController i moją metodę viewDidLoad w ramach tego kontrolera (UWAGA: initWithBill jest zastąpieniem normalnego inicjatora):

W poprzednim pliku ViewControllers .m:

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

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

Jakieś wskazówki, dlaczego nie jest nazywany?

IkegawaTaro
źródło
Używam XIB. Nie mogę usunąć z kolejki niczego w cellForItemsAtIndexPath, ponieważ nigdy nie jest wywoływana.
IkegawaTaro

Odpowiedzi:

135

Dla tych, którzy potkną się tutaj później ... powód:

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

nie była wywoływana, ponieważ element itemSize dla kolekcji ViewFlowLayout był zbyt duży.

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

Jeśli zmienię wysokość na 410, to wykona cellForItemAtIndexPath.

IkegawaTaro
źródło
Czy możesz rozwinąć trochę więcej. To samo dzieje się ze mną
user1010819
Właśnie odkryłem, że z collectionViewContentSize też trzeba uważać
Dimitar Marinov
49
W przypadku, gdy używasz autolayout - pamiętaj, aby ustawić ograniczenie wysokości w collectionView - zmarnowałem na to wiele godzin!
bpn
dla mnie ograniczenie rekordowej wysokości nie zadziałało .. poziome ograniczenia środkowe
załatwiły sprawę
4
Jeśli Twój collectionView jest ograniczony do topLayoutGuide z AutoLayout i nie powinien być przewijany w obszarze NavigationBar, pamiętaj, aby usunąć zaznaczenie Adjust Scroll View Insetsw swoim ViewController na Storyboard.
Bruno Galinari
96

W moim przypadku było to spowodowane nieprawidłową podklasą mojej klasy układu z UICollectionViewLayoutzamiastUICollectionViewFlowLayout

esilver
źródło
1
DZIĘKUJĘ CI. Niech mnie diabli, spędziłem nad tym całe wieki.
Rambatino
To też był mój problem! Jest to trochę sprzeczne z intuicją, więc nawet mi nie przyszło do głowy. Dzięki za to!
WendiKidd,
Dla mnie to samo! tak łatwo to przeoczyć! jeszcze raz dzięki
arvidurs
Facepalm, dziękuję za wskazanie tego (4 lata temu).
Milander
Miałem ten sam problem. Dzięki
Piyush Gupta,
31

Funkcja cellForItemAtIndexPath nie zostanie wywołana, jeśli nie podasz informacji o rozmiarze zawartości w widoku kolekcji.

  1. Jeśli korzystasz z układu Flow : musisz prawidłowo ustawić rozmiary elementów.
  2. Jeśli masz podklasę układu niestandardowego z UICollectionViewLayout : upewnij się, że zwracasz odpowiedni rozmiar z metody collectionViewContentSize.

W przypadku tego drugiego zauważysz również, że twój layoutAttributesForElementsRect również nie jest wywoływany. Powodem jest to, że nie określiłeś, jaki jest rozmiar twojej zawartości i domyślnie będzie to CGSizeZero. To w zasadzie mówi widokowi kolekcji, że nie masz żadnej treści do namalowania, więc nie kłopocze się pytaniem o atrybuty lub komórki.

Więc po prostu zastąp collectionViewContentSize i podaj tam odpowiedni rozmiar, to powinno rozwiązać twój problem.

Deepak GM
źródło
1
Na przykład, aby użyć pełnego dostępnego rozmiaru, zwróć collectionView.frame.size z collectionViewContentSize (nie po prostu collectionView.contentSize, która domyślnie wynosi 0, 0)
Adam Loving
Dzięki! Ta odpowiedź pomogła mi b / c Mam niestandardowy UICollectionViewLayout. Jeśli uruchomiłem aplikację w symulatorze w orientacji poziomej, niektóre komórki nie pojawiały się w początkowym widoku. Zastąpienie rozmiaru zawartości rozwiązało ten problem.
Chris Livdahl
1
Dziękuję Ci. W moim przypadku collectionViewContentSizeniepoprawnie zwrócone 0 dla szerokości, dlatego cellForItemAtIndexPathnie został wywołany.
izerik
16

Może po prostu to przeoczam, ale wygląda na to, że brakuje ci pełnomocnika i źródła danych. W pliku nagłówkowym upewnij się, że dodałeś te:

<UICollectionViewDelegate, UICollectionViewDataSource>

iw swojej metodzie viewDidLoad dodaj to:

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

Ponadto, jeśli ładujesz go za pomocą pliku .xib, upewnij się, że masz połączenie IBOutlet z UICollectionView.

Anthony Castelli
źródło
1
Nie pokazałem tego, ale mam już delegata i źródło danych zapisane w pliku nagłówkowym. Dodatkowo podłączyłem IBOutlet do myCollectionView. Delegat i źródło danych dla tego widoku kolekcji zostały ustawione na FullReceiptViewController. Dziwne jest to, że wywoływana jest metoda numberOfItemsInSection (metoda protokołu źródła danych) i zwraca liczbę całkowitą większą niż 0.
IkegawaTaro
Hmm, czy po uruchomieniu aplikacji widok Kolekcja pokazuje lub cokolwiek robi? Wygląda na to, że zawiera pewne elementy, jeśli numberOfItemsInSection zwraca wartość większą niż 0.
Anthony Castelli
Dziękuję za kontakt. Widok kolekcji jest widoczny ... Mogę to stwierdzić, ponieważ zmieniłem kolor tła. Myślę, że znalazłem problem: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; To było za duże. Jeśli zmniejszę wysokość do 410, mogę wywołać metodę cellForItemAtIndexPath.
IkegawaTaro
@AnthonyCastelli Witam, również mam do czynienia z tym samym problemem, numerOfItemsInSection jest wywoływany w pop do viewController, ale nie cellForItemsAtIndexPath. więc czy masz wskazówkę?
Bhavin Kansagara,
16

Aby uzyskać bardziej skomplikowaną hierarchię widoku, sprawdź ten blog . To uratowało mi życie!

self.automaticallyAdjustsScrollViewInsets = NO;
Jaybo
źródło
1
Spędziłem nad tym tyle czasu - i wszystko sprowadzało się do tego. Jeśli używasz scenorysu lub XIB, spójrz na nadrzędny kontroler widoku i odznacz opcję „Dopasuj wstawki widoku przewijania” w Inspektorze atrybutów, który jest domyślnie włączony. Wypróbowałem wszystkie inne odpowiedzi i nie zadziałały, sprowadzało się do tego.
etayluz
15

Jeśli Twoja klasa jest podklasą z UICollectionviewController i programowo tworzysz collectionView, użyj

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

    collectionView?.setCollectionViewLayout(layout, animated: false)
Gurjinder Singh
źródło
To jest odpowiedź rozwiązała mój problem! Metoda override func collectionView (_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} nie działa dla mnie.
Mike
8

Używałem autoukładu, aw moim przypadku brakowało ograniczenia wysokości

AamirR
źródło
6

Mój problem polegał na tym, że miałem 2 widoki kolekcji w tym samym widoku i oba współdzieliły obliczoną UICollectionViewFlowLayoutinstancję. Po utworzeniu oddzielnych instancji tego samego układu przepływu wszystko działało dobrze.

Nebyark
źródło
5

W moim przypadku to, o czym bardzo głupio zapomniałem, to zaimplementowanie UICollectionViewDataSourcemetody protokołu numberOfItemsInSection, więc to kolejna rzecz do sprawdzenia.

Dziekan
źródło
4

Upewnij się również, że reloadData nie jest wywoływana podczas aktualizowania widoku kolekcji za pomocą animacji (wstawianie, usuwanie, aktualizowanie lub wykonywanie BatchUpdates).

sasha_nec
źródło
4

W moim przypadku zestaw collectionView.prefetchingEnabled = NO;rozwiązał mój problem. Działa tylko na iOS 10.

6david9
źródło
2
Głosowałem za tą odpowiedzią jakiś czas temu i dzisiaj znowu mi pomogło: D Zasługujesz na Szlachetnego za tę odpowiedź człowieku. Dzięki jeszcze raz!
Maciek Czarnik
ta odpowiedź zadziałała dla mnie! Żałuję, że nie ma wyjaśnienia, dlaczego zostało to uwzględnione, ponieważ nigdy wcześniej nie ustawiłem tego na prawdę.
Lance Samaria
3

Stało się to dla mnie, gdy wysokość elementu == 0 przez naprawienie wywołania metody cellForItem.

Jirune
źródło
3

Dziesięć minut temu też napotkałem ten problem, popełniłem głupi błąd.

Moim zamiarem jest użycie UICollectionViewFlowLayout,

Ale z powodu błędów użyłem UICollectionViewLayout.

Vincent Sit
źródło
3

W moim przypadku zmiana półprzezroczystego paska UINavigationBar na NO rozwiązała problem.

chanil
źródło
3

W Xcode 7.0.1 napotkaliśmy ten problem, gdy skopiowaliśmy scenorys i towarzyszący mu kod z innego projektu. Widok kolekcji miał niestandardowy układ przepływu ustawiony w scenorysie. Rozwiązaniem było:

  • Usuń układ przepływu w IB
  • Skompiluj / uruchom aplikację
  • Przywróć układ przepływu

Teraz zadziałało :)

Bart van Kuik
źródło
2

Upewnij się, że numberOfSectionsInCollectionViewzwraca również dodatnią liczbę całkowitą.

W kolekcji musi znajdować się co najmniej jedna sekcja.

Eran Goldin
źródło
2

Upewnij się, że - (NSInteger) collectionView: numberOfItemsInSection: zwraca wartość dodatnią (odczytaną, większą niż zero). Może to być kwestia umieszczenia [self.collectionView reloadData]; w programie obsługi zakończenia.

RT Denver
źródło
2

Zapomniałem ustawić maskę autorezyzacji na false w widoku kolekcji:

collectionView.translatesAutoresizingMaskIntoConstraints = false
Stritt
źródło
2

Mogą to być problemy z układem. Sprawdź ostrzeżenia dotyczące układu z konsoli, jeśli istnieją.

erdikanik
źródło
2

W moim przypadku widok kolekcji nie był w pełni widoczny w swoim widoku nadrzędnym z powodu nieprawidłowych ograniczeń automatycznego układu. Zatem naprawienie ograniczeń sprawiło, że widok kolekcji był widoczny i wywołano cellForItemAtIndexPath.

Khaled Annajar
źródło
2

W storyboard / xib właściwość UICollectionView cellSize NIE MOŻE być {0, 0}

poGUIst
źródło
2

Jeśli używasz protokołów widoku kolekcji, musisz podłączyć protokoły CollectionViewDataSourcei CollectionViewDelegatedo ViewController. Gniazda konstruktora interfejsów

Declan McKenna
źródło
1

To samo przytrafiło się mnie. Miałem 2 UICollectionViews i usunąłem raz, ponieważ tego nie potrzebowałem. Po tym zdałem sobie sprawę, że CellForItemAtIndexPath nie jest wywoływany, ale inne wymagane metody. Wypróbowałem wszystkie powyższe, ale potem wykonałem standardową magię. Usunięto widok kolekcji z serii ujęć i dodano ponownie. Potem zaczęło działać. Nie wiem dlaczego i nie mam wyjaśnienia, ale może pewne problemy z połączeniem.

Hafeez
źródło
Skopiowałem mój UICollectionView z innego UIViewController w scenorysie. Usunąłem CollectionView i dodałem ponownie, aby działało. Dziękuję za Twoją odpowiedź.
Drunken Daddy
1

Właśnie rozwiązałem ten problem w nieco konkretnej sytuacji.

W moim przypadku ręcznie inicjowałem UICollectionViewController w nadrzędnym ViewController, a następnie dodałem widok UICollectionViewController jako podwidok.

Rozwiązałem problem, wywołując „setNeedsLayout” i / lub „setNeedsDisplay” na collectionView w widoku rodzicaDidAppear:

- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   [_collection.view setNeedsLayout];
   [_collection.view setNeedsDisplay];
}
Tim
źródło
1

Podczas używania UICollectionViewDelegateFlowLayoutuważaj na to, co zwraca ta funkcja. Zarówno widthi heightpowinny być większe niż 0. Użyłem windowjako odniesienia do ramki, ale ze względu na skomplikowaną hierarchię widoku okno było nilw czasie wykonywania. Jeśli potrzebujesz, dostosuj szerokość elementu na podstawie szerokości ekranu UIScreen.main.bounds.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
           UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {}
inokey
źródło
1

W moim przypadku miałem collectionVieww sposób UIStackViewz alignment = .center. Więc collectionViewnie miały szerokości. Po ustawieniu stackView.alignmentna .fillwszystko było w porządku.

Nico S.
źródło
0

W moim przypadku aktualizuję wysokość self.view (superview kolekcji collectionView) przez autolayout i MUSZĘ wywołać layoutIfNeededpo tym.

[self.view mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(@(height));
}];
[self.view layoutIfNeeded];
Panie Ming
źródło
0

W moim przypadku musiałem dostosować szacowany rozmiar treści. rozmiar treści tego nie zrobił.

  let layout = collectionVC.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: 100, height: 100)
    layout.estimatedItemSize = CGSize(width: 100, height: 100)
tobi
źródło
0

Miałem podobny problem. Ale zamiast tego cellForItemAtIndexPathzostał wywołany, gdy liczba elementów była> 1, ale nie wtedy, gdy był tylko jeden element. Wypróbowałem wiele z proponowanych tutaj rozwiązań i podobnie jak wiele stwierdziłem, że ma to związek z wymiarowaniem przedmiotów. Dla mnie rozwiązaniem była zmiana szacunkowego rozmiaru UICollectionViewz automatycznego na niestandardowy .

Ustaw szacunkowy rozmiar na Niestandardowy

Wouter
źródło
-1

Zatopiłem się trochę w tym problemie, który pojawił się z CollectionView w kontrolerze widoku Contained załadowanym z serii ujęć. Skończyło się na usunięciu zawartego kontrolera widoku i odtworzeniu go w scenorysie, a to wydawało się pozbyć problemu. Domyślam się, że miało miejsce jakieś uszkodzenie storyboardu.

wfbarksdale
źródło