Интересная проблема с UICollectionView reloadData
При работе с UICollectionView
в моем приложении у меня возникла странная проблема, связанная с перезагрузкой данных. После долгих отладочных и аналитических журналов я пришел к выводу, что если за reloadData
сразу следует insertItemsAtIndexPaths
, гарантируется страшная ошибка ниже:
Имя: NSInternalInconsistencyException
Причина: Недействительное обновление: недействительно количество элементов в разделе 0. Количество элементов, содержащихся в существующий раздел после обновления (1) должен быть равен числу элементы, содержащиеся в этом разделе перед обновлением (1), плюс или минус количество вставленных или удаленных элементов из этого раздела (1 вставлено)...
Только для этого всегда существует то, что внутри UICollectionView
по-прежнему занят reloadData
, когда приходит вызов insertItemsAtIndexPaths
. Тот факт, что "collectionView:numberOfItemsInSection
" вызывается дважды в строке до завершения insertItemsAtIndexPaths
, похоже, поддерживает это, поскольку этот метод никогда не вызывается дважды в строке при вызове других случаев.
Кто-нибудь видел подобное поведение или может подтвердить мой анализ или даже предложить правильное обходное решение?
Обновление: любое да, я убедился, что все соответствующие вызовы происходят в основном потоке.
Обновление 2. Поскольку аргументация о том, чтобы попасть в эту ситуацию вообще, была поставлена под сомнение: я использую Monotouch, и этот код предназначен для хранения общих коллекций .Net Collections это событие в соответствующие вызовы, чтобы привязать UICollectionView к коллекции в синхронизации. Когда исходная коллекция очищается, она реагирует с действием Reset, за которым следует один или несколько действий Add, когда элементы вставлены в него, что приводит к описанной выше проблеме. Надеюсь, это поможет.
Ответы
Ответ 1
Когда вы вызываете insertItemsAtIndexPaths
(removeItemsAtIndexPaths
аналогично), вы сообщаете своему коллективу, что его источник данных теперь имеет больше доступных элементов и что он должен вставлять эти доступные элементы по указанным вами указателям.
Он проверяет ваш источник данных, является ли это утверждение истинным, и если он обнаруживает, что количество старых предметов и количество предметов, которые вы указали вставляете, не равно количеству новых предметов, в нем говорится, что он не может выполнить обновление, поскольку вы лгали о том, сколько элементов вы изменили.
Теперь, что вы делаете, вы сообщаете, что ваш сборщик должен перезагрузить все свои данные из своего источника данных (с новыми данными), и сразу после этого вы скажете, что вы вставили x элементов. Это ложное утверждение, так как вы просто перезагрузили коллекцию, которая обновила количество элементов, и поэтому количество элементов до обновления равно количеству элементов после обновления (вы ничего не делаете), а не увеличено на количество указателей, которые вы указали.
Я надеюсь, что вы все еще со мной, потому что здесь ваше решение:
Удалите reloadData
до insertItemsAtIndexPaths
, так как это нарушает его утверждения и будет генерировать исключения при неправильном использовании. Если вы хотите перезагрузить сборку перед вставкой элементов, убедитесь, что вы выполняете insertItemsAtIndexPaths
сразу после изменения элементов в источнике данных.
Прочитайте документацию по этому методу здесь.