błąd iOS 10: UICollectionView otrzymał atrybuty układu dla komórki ze ścieżką indeksu, która nie istnieje

Po uruchomieniu aplikacji na urządzeniu z systemem iOS 10 pojawia się błąd:]}

UICollectionView otrzymał atrybuty układu dla komórki ze ścieżką indeksu, która nie istnieje

W iOS 8 i 9 działa dobrze. Badałem i odkryłem, że jest to coś związanego z unieważnieniem układu widoku kolekcji. Próbowałem wdrożyć to rozwiązanie bez powodzenia, więc chciałbym prosić o bezpośrednią pomoc. To jest mój widok hierarchii:
->Table view 
    ->Each cell of table is a custom collection view [GitHub Repo][1]
        ->Each item of collection view has another collection view

What I have tried is to insert

    [self.collectionView.collectionViewLayout invalidateLayout];

W

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

Obu widoków kolekcji.

Również próbowałem unieważnić układ przed wykonaniem przeładowania danych, nie działa...

Czy ktoś mógłby mi podać jakieś wskazówki?
Author: cmacera, 2016-10-05

18 answers

Przydarzyło mi się to, gdy liczba komórek w collectionView zmieniła się. Okazuje się, że brakowało mi invalidateLayout po wywołaniu reloadData. Po dodaniu nie doświadczyłem już żadnych awarii. Apple wprowadziło pewne modyfikacje do collectionViews w iOS10. Myślę, że to jest powód, dla którego nie doświadczamy tego samego problemu na starszych wersjach.

Oto mój ostatni kod:

[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];

//Swift 4.2 Version
collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
 141
Author: Katrin Annuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-19 11:49:10

Jeśli masz własny układ, pamiętaj, aby wyczyścić pamięć podręczną (UICollectionViewLayoutAttributes) podczas nadpisywania prepare func

    override func prepare() {
       super.prepare()
       cache.removeAll()
    }
 48
Author: ArturC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-18 10:02:07

Napotkałem również ten problem z 2 collectionViews w tym samym widoku, ponieważ dodałem ten sam UICollectionViewFlowLayout w obu kolekcjach:

let layout = UICollectionViewFlowLayout()
collectionView1.collectionViewLayout = layout
collectionView2.collectionViewLayout = layout

Oczywiście zawiesza się przy przeładowaniu danych, jeśli dane collectionView1 ulegną zmianie. Jeśli to może komuś pomóc.

 19
Author: Aximem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-01 08:58:26

Poprzednia odpowiedź pomaga, ale jeśli użyjesz autoezizujących komórek, ich rozmiar będzie nieprawidłowy.

 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
 layout.estimatedItemSize = CGSizeMake(60, 25);
 layout.itemSize = UICollectionViewFlowLayoutAutomaticSize;             
 self.collectionView.collectionViewLayout = layout;

Rozwiązuję ten problem zastępując

[self.collectionView reloadData];

Do

[self.collectionView reloadSections:indexSet];
 6
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-28 15:10:52

ODPOWIEDŹ @ Katrin bardzo pomogła, ale mogłem osiągnąć jeszcze lepsze wyniki dodając jeszcze jedną linijkę:

collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
collectionView.layoutSubviews() // <-- here it is :)

Nie mogę teraz powiedzieć, czy mogę odtworzyć crash z tej linii, czy nie, ale myślę, że był jeden... Więc nadal nie Srebrna kula, ale coś.

 6
Author: m8labs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-26 22:20:36

Resetowanie układu UICollectionView rozwiązało problem dla mnie:

let layout = UICollectionViewFlowLayout()
collectionView?.collectionViewLayout = layout
 4
Author: krlbsk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 12:20:22

Telefon nie zapobiegł awarii w moim przypadku. (Zadziałało, jeśli liczba elementów w widoku kolekcji wzrosła, ale nie, jeśli zmniejszyła się). Kontekst: mam UICollectionView wewnątrz UITableViewCell i kiedy komórka tabeli jest ponownie używana, resetuję delegatów collectionView. Naprawiłem problem nie przez unieważnienie pamięci podręcznej, ale przez odtworzenie obiektu layout za każdym razem, gdy zresetowałem delegata, a następnie wywołałem reloadData ():

foo.dataSource = newDataSource
foo.delegate = newDelegate
foo.fixLayoutBug()
foo.reloadData()

func fixLayoutBug() {
    let oldLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let newLayout = UICollectionViewFlowLayout()
    newLayout.estimatedItemSize = oldLayout.estimatedItemSize
    newLayout.footerReferenceSize = oldLayout.footerReferenceSize
    newLayout.headerReferenceSize = oldLayout.headerReferenceSize
    newLayout.itemSize = oldLayout.itemSize
    newLayout.minimumInteritemSpacing = oldLayout.minimumInteritemSpacing
    newLayout.minimumLineSpacing = oldLayout.minimumLineSpacing
    newLayout.scrollDirection = oldLayout.scrollDirection
    newLayout.sectionFootersPinToVisibleBounds = oldLayout.sectionFootersPinToVisibleBounds
    newLayout.sectionHeadersPinToVisibleBounds = oldLayout.sectionHeadersPinToVisibleBounds
    newLayout.sectionInset = oldLayout.sectionInset
    newLayout.sectionInsetReference = oldLayout.sectionInsetReference
    collectionViewLayout = newLayout
}
 4
Author: Nick Kallen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-13 13:12:08

Nie jest najlepiej przeładowywać dane za każdym razem (powinieneś użyć insertItems i deleteItems, a nawet przeładować sekcje). Ale... po stwierdzeniu, że w niektórych przypadkach jest to poprawne so, możesz to zrobić:

collectionView.dataSource = nil

collectionView.delegate = nil

/*... All changes here. ... */

collectionView.dataSource = self

collectionView.delegate = self

collectionView.reloadData()
 3
Author: Kevin Bel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-17 01:28:50

W moim przypadku zmieniałem stałą NSlayoutConstraint

self.collectionViewContacts.collectionViewLayout.invalidateLayout()

            UIView.animate(withDuration: 0.3) {
                self.view.layoutIfNeeded()
            }


            self.collectionViewContacts.reloadData()

Rozwiązałem problem

 3
Author: jeff ayan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 19:11:51

Miałem problem używając RxDataSources z RxCollectionViewSectionedAnimatedDataSource i rozwiązałem go łącząc dwie odpowiedzi. Muszę invalidateLayout() po reaktywnym przeładowaniu mojej kolekcji:

    ...
    .asDriver(onErrorJustReturn: [])
    .do(onNext: { [weak self] _ in
        DispatchQueue.main.async {
            self?.collectionViewLayout.invalidateLayout()
            self?.collectionView.layoutSubviews()
        }
    }).drive(collectionView.rx.items(dataSource: collectionController.dataSource))
    .disposed(by: disposeBag)

I wyczyść cache array (s) W metodzie prepare() layout. Oto kod:

override func prepare() {
    super.prepare()
    cache.removeAll()
    guard let collectionView = collectionView,
        collectionView.numberOfSections > 0,
        let delegate = delegate else {
        return
    }
    ...
 2
Author: Mol0ko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-11 14:30:05

Jeśli chcesz utrzymać pozycję przewijania i naprawić awarię, możesz użyć tego:

collectionView.reloadData()
let context = collectionView.collectionViewLayout.invalidationContext(forBoundsChange: collectionView.bounds)
context.contentOffsetAdjustment = CGPoint.zero
collectionView.collectionViewLayout.invalidateLayout(with: context)
 1
Author: Mati Bot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-09 04:58:13

Miałem do czynienia z podobnym problemem podczas pokazywania-ukrywania widoku kolekcji za pomocą animowanych zmian ograniczeń. Moje rozwiązanie opiera się na istniejących odpowiedziach.

self.filtersCollectionView.reloadData()
if isNeedToUpdateConstraint {
    filtersCollectionViewHeightLayoutConstraint.constant = updatedHeight
    UIView.animate(withDuration: 0.1, animations: {
        self.view.setNeedsLayout()
    }, completion: { completion in
        if completion {
            self.filtersCollectionView.collectionViewLayout.invalidateLayout()
        }
    })
}
 1
Author: dimazava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-23 12:26:33

Ja też miałem ten problem. W moim przypadku do widoku kolekcji został zastosowany custom UICollectionViewLayout i problem polegał na tym, że miał stare dane dotyczące liczby komórek, które powinny być wyświetlane. To zdecydowanie coś, co możesz sprawdzić, gdy zobaczysz UICollectionView received layout attributes for a cell with an index path that does not exist

 0
Author: Trev14,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 22:25:03

Udało mi się to rozwiązać odtwarzając collectionViewLayout przed wywołaniem reloadData()

Problem był prawdopodobnie związany z tym, że miałem osobną instancję dataSource (tzn. nie kontroler widoku trzymający collectionView), a podczas wymiany źródła danych może pojawić się awaria.

 0
Author: ullstrm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 11:50:27

Mi też się to przydarzyło, ale to dlatego, że mój UICollectionViewDataSourcesię zmienił, a ja nie zadzwoniłem -[UICollectionView reloadData]. W moim przypadku miałem następującą strukturę danych:

struct Bar { let name: String }
struct Foo { let name: String; let bars: [Bar] }

Miałem dwa UICollectionView s: jeden dla Foo s i jeden dla Bars. W moim -collectionView:didSelectItemAtIndexPath: miałem następujące:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  if (collectionView == self.fooCollectionView) {
    self.selectedFoo = self.foos[indexPath.row];
    [self.barCollectionView reloadData];
    self.fooCollectionView.hidden = YES;
    self.barCollectionView.hidden = NO;
  } else if (collectionView == self.barCollectionView) {
    // do some stuff with the selected bar

    self.selectedFoo = nil;
    // This -reloadData call fixed my error. I thought I didn't
    // need it since my UICollectionView was hidden
    [self.barCollectionView reloadData];
    self.barCollectionView.hidden = YES;
    self.fooCollectionView.hidden = NO;
  }
}

Bez połączenia -reloadData, widzę awarię, gdy obracam urządzenie.

 0
Author: Heath Borders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-31 19:54:02

Po spędzeniu dwóch dni czasu poniższy kod rozwiązał problem. Przed załadowaniem collectionview napisz poniższy kod.

let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
collecView.collectionViewLayout = flowLayout 
collecView.delegate = self
collecView.dataSource = self
collecView.reloadData()

Następnie awaria zostanie rozwiązana, ale znajdziesz problem w komórkach collectionview, ponieważ komórki są skompresowane lub nie zgodnie z Twoim projektem. Następnie wystarczy wiersz kodu po scrolldirection line

flowLayout.itemSize = CGSize(width: 92, height: 100)

Za pomocą powyższego wiersza kodu można dostosować układ komórki collectionview.

Mam nadzieję, że to komuś pomoże.
 0
Author: Arshad Shaik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 12:26:54

W moim przypadku zmieniałem stałą NSLayoutConstraint żadne z powyższych rozwiązań nie działało dla mnie. dzięki @ jeff ayan, którego odpowiedź dała mi podpowiedź. Rozwiązałem problem z tym kodem

override func prepareForReuse() {
    super.prepareForReuse()
    imagesCollectionHeight.constant = 100 // changing collectionview height constant
    imageContainerWidth.constant = 100  //changing width constant of some view
    self.layoutIfNeeded() // this line did the trick for me
}

Hope it helps someone

 0
Author: Gulfam Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-17 15:46:54

:

[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];

Ten kod wydaje się zmuszać collectionView do przewinięcia do pierwszej komórki przed przeładowaniem danych, co wydaje się powodować błąd w moim przypadku.

 0
Author: Javier Alzueta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-03 21:51:58