Мое приложение имеет UITableViewController, который получает «Недопустимое обновление: недопустимое количество строк в разделе 0 ...» после добавления строк. Дело в том, что это происходит только в% 0,2 сеансов. Наше приложение имеет миллионы сеансов, поэтому сбои складываются.UITableView случайный сбой при добавлении строк
Поток прост. Это часть функции, которая соответствует музыке пользователя с нашим каталогом видео. Фоновая нить выполняет ряд запросов. Запрос исчезает, ответ возвращается с результатами, затем эти результаты добавляются в таблицуView на одной из наших вкладок. Запросы идут в партиях и могут содержать множество результирующих строк. Поэтому вместо вызова reloadData после того, как пакет входит, я хотел бы добавить их правильно. Работает потрясающе, но иногда падает.
Я смог воспроизвести это один раз на устройстве. Это никогда не происходило на симуляторе. Насколько я знаю, авария достаточно случайна, хотя в основном это происходит на 3gs. Наименьшее количество аварий приходится на 4s.
Вот код. Ответ возвращается. В этом случае allMatches - это каждое совпадение до сих пор (источник данных для таблицы). batchMatches - количество новых исполнителей. Оба являются массивами:
[self.tableView beginUpdates];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (int i = [allMatches count] - [batchMatches count]; i < [allMatches count]; ++i) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[paths addObject: indexPath];
}
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
[paths release];
Код довольно прост. Он просто добавляет строки в конец, по одному для каждого результата. Никогда не удаляется. Примером полного сообщения об исключении является «Недопустимое обновление: недопустимое количество строк в разделе 0. Количество строк, содержащихся в существующем разделе после обновления (131), должно быть равно количеству строк, содержащихся в этом разделе перед обновлением (131), плюс или минус количество строк, вставленных или удаленных из этого раздела (20 вставленных, 0 удаленных) и плюс или минус количество строк, перемещенных в или из этого раздела (0 перемещен, 0 перемещен). " Числа повсюду в реальных отчетах о сбоях, поэтому это не определенный номер партии.
Как я уже сказал, он почти всегда работает. И он падает обычно на 3GS. Мне интересно, может ли это быть ошибкой структуры. Я всегда мог вызывать reloadData после каждой партии, но это приводит к уродливому миганию ячеек таблицы каждый раз. С целью я вызвал исключение, и, похоже, после этого таблица мертва, поэтому я не смог сделать try/catch с reloadData как резерв в блоке catch.
Может ли кто-нибудь пролить некоторый свет? Извинения за длину этого поста.
EDIT: запросы сервера выполняются с использованием NSOperationQueue, поэтому они находятся на фоновом потоке. Когда ответ возвращается, я отправляю уведомление по основному потоку, из-за чего запускается код таблицы. Уведомление опубликовано так:
NSNotification *notification = [NSNotification notificationWithName:notificationName object:self];
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
Сообщение notificiation просто обертка [[NSNotificationCenter defaultCenter] postNotification: уведомление]. Таким образом, код таблицы должен быть в основном потоке.
Эй, большое спасибо за ответ. Я добавил свой вопрос, чтобы объяснить, что код таблицы работает в основном потоке. В фоновом режиме работает только взаимодействие с сервером. Я выбрал другой подход, чем вы. Я использую NSOperationQueue для запуска связи с сервером. Затем NSNotification отправляется из потока bg через performSelectorOnMainThread. Поэтому noitifcation отправляется в основной поток.Затем ViewController получает это уведомление, которое должно быть в основном потоке, который обновляет таблицу. Вы видите какие-либо проблемы с моим подходом к вашему? Еще раз спасибо. –
Я не вижу разницы между обоими подходами. Оба выполняют асинхронный код в основном потоке. Убедитесь, что массив данных не может быть изменен фоновым потоком при обновлении таблицы. Чтобы быть в безопасности, вы можете отправить уведомление синхронно. Просто установите waitUntilDone на YES. – Felix
DUDE, я думаю, вы, возможно, решили это. У меня было waitUntilDone установлено значение NO. Делает прекрасный смысл: сообщения уведомлений, таблица начинает обновляться, происходит другое уведомление, таблица начинает обновляться во второй раз и сбой! Я буду знать наверняка после следующего обновления, но это имеет смысл, и имеет смысл, что это произошло на 3g, главным образом потому, что это устройство является самым медленным. Я, кстати, с VEVO, поэтому проверьте приложение, если хотите. Еще раз спасибо. ТЫ ЖЖЕШЬ! –