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

Ошибка подтверждения в UICollectionViewData indexPathForItemAtGlobalIndex

Я использую performBatchUpdates() для обновления моего представления коллекции, где я делаю полное обновление, т.е. удаляю все, что было в нем, и снова вставляю все. Обновления пакета выполняются как часть Observer, которая привязана к NSMutableArray (bingDataItems).

cellItems - это массив, содержащий элементы, которые будут или будут вставлены в представление коллекции.

Вот код:

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    cultARunner *_cultARunner = [cultARunner getInstance];
    if ( [[_cultARunner bingDataItems] count] ) {
        [self.collectionView reloadData];
        [[self collectionView] performBatchUpdates: ^{

            int itemSize = [cellItems count];
            NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];

            // first delete the old stuff
            if (itemSize == 0) {
                [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]];
            }
            else {
                for( int i = 0; i < cellItems.count; i++ ) {
                    [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
                }
            }
            [cellItems removeAllObjects];
            if(itemSize) {
                [self.collectionView deleteItemsAtIndexPaths:arrayWithIndexPaths];
            }

            // insert the new stuff
            arrayWithIndexPaths = [NSMutableArray array];
            cellItems = [_cultARunner bingDataItems];
            if ([cellItems count] == 0) {
                [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]];
            }
            else {              
                for( int i = 0; i < [cellItems count]; i++ ) {
                    [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
                }
            }
            [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
        }
        completion:nil];
    }
}

Я получаю эту ошибку, но не во все времена (почему?)

2012-12-16 13:17:59.789 [16807:19703] *** Assertion failure in -[UICollectionViewData indexPathForItemAtGlobalIndex:], /SourceCache/UIKit_Sim/UIKit-2372/UICollectionViewData.m:442
2012-12-16 13:17:59.790 [16807:19703] DEBUG:    request for index path for global index 1342177227 when there are only 53 items in the collection view

Я проверил единственный поток, в котором упоминалась одна и та же проблема: Ошибка UICollectionView Assertion, но это не очень понятно, т.е. выполнение [collectionview reloadData] нецелесообразно в performBatchUpdates().

Любые предложения о том, что здесь может быть неправильным?

4b9b3361

Ответ 1

Наконец-то! Хорошо, вот что привело к этой катастрофе для меня.

Как уже отмечалось ранее, я создавал дополнительные представления, чтобы предоставлять заголовки разделов в стиле пользовательского стиля для моего представления коллекции.

Проблема заключается в следующем: кажется, что indexPath дополнительного представления ДОЛЖЕН соответствовать индексу PAT из существующей ячейки в коллекции. Если указательный путь дополнительного представления не имеет соответствующей обычной ячейки, приложение будет аварийно завершено. Я считаю, что просмотр коллекции пытается получить информацию для дополнительной ячейки представления по какой-либо причине во время процедуры обновления. Он падает, когда он не может его найти.

Надеюсь, это тоже решит вашу проблему!

Ответ 2

Это правильное обходное решение для этого сбоя:

Каждое из ваших дополнительных представлений связано с определенным указательным путем. Если у вас нет ячейки на этом пути индекса (начальная загрузка, вы удалили строку и т.д.), Верните высоту 0 для вашего дополнительного представления через делегат макета.

Итак, для макета потока реализуем UICollectionViewDelegateFlowLayout

(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section

(и соответствующий метод нижнего колонтитула, если вы используете нижние колонтитулы) со следующей логикой

if ( you-have-a-cell-at-the-row-for-this-section )
    return myNormalHeaderSize;
else return CGSizeMake( 0,0 );

Надеюсь, это поможет!

Ответ 3

reloadData не работает для меня, потому что вся цель использования performBatchUpdates заключается в том, чтобы получить анимированные изменения. Если вы используете reloadData, вы обновляете данные только, но без анимации.

Поэтому предложения "replace performBatchUpdates с reloadData" в значительной степени говорят "откажитесь от того, что вы пытаетесь сделать".

Прошу прощения, я просто разочарован, потому что эта ошибка продолжает приходить ко мне, пока я пытаюсь сделать некоторые великолепные анимированные обновления, и моя модель на 100% правильна, это некоторая магия iOS внутри, которая сломалась и заставила меня полностью изменить мои решения.

Мое мнение таково, что Collection Views по-прежнему не работает и не может выполнять сложные анимированные обновления, даже если они должны быть в состоянии. Потому что это было то же самое для Table Views, но теперь они довольно стабильны (требуется время).

//Редактировать (1 сентября 2013 г.) Сообщенная ошибка закрыта сейчас, так что эти проблемы, похоже, уже были решены Apple.

Ответ 4

У меня была та же проблема.

Я пробовал несколько вариантов, но последний, который работает, [self.collectionView reloadData], где "self.collectionView" - это имя вашего вида коллекции.

Я пробовал следующие методы, прямо из "Справочника класса UICollectionView": вставка, перемещение и удаление элементов.

Сначала они использовались для "перемещения" элемента из одной секции в другую.

  • deleteItemsAtIndexPaths:

  • insertItemsAtIndexPaths:

Затем я попробовал moveItemAtIndexPath:toIndexPath:.

Все они произвели следующую ошибку:

Ошибка утверждения в - [UICollectionViewData indexPathForItemAtGlobalIndex:],/SourceCache/UIKit_Sim/UIKit-2372/UICollectionViewData.m:442

Итак, попробуйте метод reloadData.

Ответ 5

Если вы удалите последнюю ячейку из раздела, содержащего верхний/нижний колонтитул, появится ошибка.

Я попытался вернуть nil для размера/элемента head/footer size/element в это время, и этот иногда устраняет проблему.

Параметры:

  • Перезагрузите весь вид таблицы вместо анимации удаления последнего элемента.
  • Добавьте дополнительную невидимую базовую ячейку размером менее 1.

Ответ 6

Ошибка с сыром, которая может привести к этой ошибке, заключается в повторном использовании одного и того же UICollectionViewFlowLayout в нескольких коллекционных видах на одном и том же контролере просмотра! Просто запустите разные flowLayouts для каждого коллекционного просмотра, и вам будет хорошо идти!

Ответ 7

Я столкнулся с этой проблемой, когда я удаляю одну из ячеек из моего представления коллекции.

Проблема заключалась в том, что я использую собственный макет, а вызов layoutAttributesForElementsInRect возвращался больше, чем количество ячеек в представлении коллекции после удаления.

Очевидно, UICollectionView просто выполняет итерацию через массив, возвращаемый методом, не проверяя количество ячеек.

Модификация метода для возврата того же числа атрибутов макета разрешила сбой.

Ответ 8

Я все еще не мог понять, как глобальный индекс был настолько увеличен, но я решил свою проблему, вставив временный элемент в базовый массив данных, т.е. cellItems и вызвав [self.collectionview reloadData] в viewDidLoad().

Это временно вставляет ячейку-заполнитель в виде коллекции, пока я не запускаю фактический процесс, используя performBatchUpdates().