Сбой с UICollectionView и настраиваемым макетом потока

Я реализовал закрепленные заголовки разделов для представления коллекции, используя http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using в качестве отправной точки, и они работают.

Но я наблюдаю очень странную аварию.

Когда я нажимаю подробное представление редактора, меняю имя элемента таким образом, чтобы он перемещался из одного раздела в другой (подумайте, изменяя фамилию человека в списке контактов, который сгруппирован по первой букве фамилии), а затем вернуться к просмотру коллекции вылетает с жалобой

UICollectionView received layout attributes for a cell with an index path that does not exist

Вот как выглядит исполнение:

В подробном представлении редактора я изменяю имя элемента таким образом, чтобы он переместился из раздела X в раздел Y.

Модель элемента излучает уведомление «имя изменено».

Контроллер корневого представления, которому принадлежит представление коллекции, улавливает это уведомление об изменении имени, перестраивает свои внутренние индексы, а затем вызывает -reloadData в представлении коллекции. Это все хорошо.

Я нажимаю кнопку «Назад» в пользовательском интерфейсе, и происходит следующий поток (подтвержденный с помощью отладчика и вызовов NSlog пещерного человека)

  • numberOfSectionsInCollectionView: вызывается, и мой код возвращает правильное количество разделов
  • collectionView: numberOfItemsInSection: вызывается для каждого раздела, и возвращается правильное количество элементов
  • вызывается мой настраиваемый макет потока -layoutAttributesForElementsInRect :. Первое, что я делаю, это вызываю [super layoutAttributesForElementsInRect], чтобы получить базовый макет.

Регистрируя унаследованный макет базовой линии, я вижу атрибуты предыдущего расположения ячеек, а не текущего. Например, макет предназначен для расположения до правок, которые я только что внес. Итак, неправильные разделы и / или ячейки в неправильных разделах.

Вот что меня потрясает.

Если я закомментирую всю реализацию -layoutAttributesForElementsInRect, она все равно вылетит. Но, если я закомментирую:

- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
    return YES;
}

Тогда он работает правильно.

Это говорит мне, что представление коллекции или что-то в макете потока кэширует результаты, но только если макет потока должен InvalidateLayoutForBoundsChange

Обратите внимание: если я просто использую ванильный UICollectionViewFlowLayout, все работает нормально.

TL; DR

Пользовательский UICollectionViewFlowLayout, если -shouldInvalidateLayoutForBoundsChange возвращает ДА, получает устаревшие атрибуты макета из [super layoutAttributesForElementsInRect]

Любые идеи?


person TomorrowPlusX    schedule 10.12.2014    source источник
comment
Убедитесь, что вы сохраняете атрибуты layoutAttributes для каждого типа элемента по отношению к соответствующему indexPath в отдельных словарях в методе prepareLayout. Вернуть тот же атрибут layoutAttribute для соответствующего индекса из словарей соответствующих элементов.   -  person dev gr    schedule 10.12.2014
comment
Вы в этом разобрались? Я думаю, что у меня почти такая же проблема.   -  person Hilton Campbell    schedule 18.04.2015
comment
Я исправил это, но хакерским способом. В итоге у меня была заметка о представлении коллекции, если она была / скрыта / при внесении изменений, и отложить вызов для перезагрузки данных в этой ситуации для viewDidAppear:   -  person TomorrowPlusX    schedule 19.04.2015


Ответы (1)


Я решил это, удалив переопределение shouldInvalidateLayoutForBoundsChange: и вместо этого реализовав scrollViewDidScroll: в делегате представления коллекции, чтобы сделать макет недействительным:

override func scrollViewDidScroll(scrollView: UIScrollView) {
    collectionView?.collectionViewLayout.invalidateLayout()
}

Это сохраняет липкие заголовки, но предотвращает сбои.

person Hilton Campbell    schedule 18.04.2015