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?


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.


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


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.


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.


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;

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)

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


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.


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.


4

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


4

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


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.


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.


3

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


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


2

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

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


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.


2

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

collectionView.translatesAutoresizingMaskIntoConstraints = false

2

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


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.


2

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


2

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


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.


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

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

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.


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

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)

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


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.