Подтвердить что ты не робот

Исключение UICollectionView в UICollectionViewLayoutAttributes из iOS7

Я сделал вид в CollectionView с CustomLayout. В iOS6 он отлично работал, но iOS7 выдает такое исключение.

Завершение приложения из-за неперехваченного исключения "NSInternalInconsistencyException", причина:

'атрибуты макета для дополнительного элемента в пути индекса ({длина = 2, путь = 0 - 0}) изменены из CustomSupplementaryAttributes: 0xd1123a0 путь индекса: (NSIndexPath: 0xd112580 {length = 2, path = 0 - 0}); тип элемента: (идентификатор); frame = (0 0; 1135,66, 45); zIndex = -1; к CustomSupplementaryAttributes: 0xd583c80 индексный путь: (NSIndexPath: 0xd583c70 {length = 2, path = 0 - 0}); тип элемента: (идентификатор); frame = (0 0; 1135,66, 45); zIndex = -1; без аннулирования макета

4b9b3361

Ответ 1

Перед обновлением необходимо аннулировать существующий макет, см. конец сообщения об ошибке:

без аннулирования макета

[collectionViewLayout invalidateLayout];

Документация Apple для UICollectionViewLayout

Ответ 2

iOS 10

В iOS 10 вводится новая функция, она Cell Prefetching. Это позволит динамической позиции аварии SupplementaryView. Чтобы выполнить старое поведение, необходимо отключить prefetchingEnabled. Он true по умолчанию в iOS 10.

// Obj-C
// This function is available in iOS 10. Disable it for dynamic position of `SupplementaryView `.
if ([self.collectionView respondsToSelector:@selector(setPrefetchingEnabled:)]) {
    self.collectionView.prefetchingEnabled = false;
}

// Swift
if #available(iOS 10, *) { 
    // Thanks @maksa
    collectionView.prefetchingEnabled = false 

    // Swift 3 style
    colView.isPrefetchingEnabled = false   
}

Я ненавижу эту проблему. Я трачу 2 дня на эту проблему. Ссылка на Предварительная выборка ячейки @iOS 10.


iOS 9 и до...

@Away Lin прав.. Я решаю ту же проблему, реализуя этот метод делегата.

My Custom UICollectionViewLayout изменит атрибуты в layoutAttributesForElementsInRect. Позиция секции динамическая, а не статическая. Итак, я получаю предупреждения о layout attributes for supplementary item at index path ... changed from ... to .... Перед изменениями следует вызывать связанные методы invalideLayout.

И после реализации этого метода делегата для возврата true метод invalidateLayoutWithContext: будет вызываться при прокрутке UICollectionViewLayout. По умолчанию он возвращает false.

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

Из Apple Docs

Возвращаемое значение true, если для представления коллекции требуется обновление макета или false, если макет не нуждается в изменении.

Обсуждение По умолчанию этот метод возвращает false. Подклассы могут переопределять его и возвращать соответствующее значение на основе должны ли изменения в границах вида коллекции требовать изменений к компоновке ячеек и дополнительных просмотров.

Если границы вида коллекции меняются и этот метод возвращается true, представление коллекции аннулирует макет, вызывая invalidateLayoutWithContext: метод.

Доступность Доступна в iOS 6.0 и более поздних версиях.


И еще...

Хороший пример проекта на GitHub для пользовательского UICollectionViewLayout.

Ответ 3

У меня было то же исключение: в iOS 7 вам теперь нужно переопределить унаследованный isEqual: в вашем подклассе UICollectionViewLayoutAttributes, как указано в документации Apple здесь.

Ответ 4

Я решил свою проблему, переопределив метод в подклассе UICollectionViewFlowLayout:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound

return YES

Ответ 5

У меня тоже была эта проблема, потому что у меня был код, зависящий от размера содержимого коллекции. Мой код получал доступ к размеру содержимого с помощью collectionView!.contentSize вместо collectionViewContentSize.

Первый использует свойство collectionView для UICollectionViewLayout, в то время как последнее использует свойство макета, выполненное по умолчанию. В моем коде при первом запросе атрибутов атрибут contentSize еще не был установлен.