Проблема с производительностью: удаление большого количества ячеек из UITableView - PullRequest
0 голосов
/ 15 декабря 2010

У меня есть табличное представление с более чем 1000 ячейками (на экране отображается около 10). После действия пользователя «фильтровать» я хочу удалить около 80% из них, затем через второй фильтр еще 80%. При работе с 100 ячейками это примерно мгновенно, но с 1000 требуется 0,5 секунды для завершения метода [tableView endUpdates], и это полностью разрушает пользовательский опыт.

Я создаю массив путей индекса следующим образом:

for (int i=1; i<[appDelegate.myArray count]; i++) {   //more than 1000 objects in myArray
    if (![[appDelegate.myArray objectAtIndex:i] myTest]) {  //myTest returns a BOOL 
        [appDelegate.rowsToDelete addObject:[NSIndexPath xxxxx]]; //the index path of the object that just failed the test and must be removed];
 }
}
[self.myTableViewController.tableView deleteRowsAtIndexPaths:appDelegate.rowsToDelete withRowAnimation:UITableViewRowAnimationRight];

Я испробовал 2 решения, одно из которых является многопоточным, чтобы мой пользователь мог видеть, как другие части пользовательского интерфейса перемещаются в процессе обновления tableView. Но если он запускает другой уровень фильтрации, это часто приводит к долгому ожиданию, если не к сбою.

Я также попытался удалить первые несколько ячеек (те, что на экране), а затем просто удалить другие объекты, которые не прошли тест, из источника данных, не удаляя их соответствующие ячейки из tableView, поскольку они находятся вне поля зрения. Это дает хороший, быстрый результат, но у меня тогда возникают проблемы с количеством строк, таких как:

'Неверное обновление: недопустимое количество строк в разделе 0. Число строк, содержащихся в существующем разделе после обновления (94), должно быть равно количеству строк, содержащихся в этом разделе до обновления (927). ), плюс или минус количество строк, вставленных или удаленных из этого раздела (0 вставлено, 215 удалено). '

У кого-нибудь была такая проблема с производительностью? способы решить это? Ура, CD

Ответы [ 3 ]

0 голосов
/ 01 февраля 2011

Возможно, вы захотите просто выполнить фильтрацию и перезагрузить все табличное представление, используя новое количество строк. Нет смысла делать все эти анимации удаления, если они все равно оказываются вне поля зрения. Или просто выясните, какая часть видима, затем загрузите и удалите только те строки, которые в данный момент видны пользователю?

0 голосов
/ 04 августа 2012

Я согласен с @ futureelite7, что вам следует перезагрузить источник данных, а не манипулировать представлением. Я предложил решение подобного вопроса здесь .

Основная идея - вызвать reloadSections: withRowAnimation: и в ваших методах UITableViewDataSource включить сегментированный элемент управления selectedSegmentIndex.

Если предположить, что ваши данные плоские (только один раздел), они будут выглядеть примерно так:

- (IBAction)segmentSwitch:(id)sender
{
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    switch (self.segmentedControl.selectedSegmentIndex)
    {
        default:
        case 0:
            return [self.allRows count];
        case 1:
            return [self.onlySomeRows count];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id data;
    switch (self.segmentedControl.selectedSegmentIndex)
    {
        default:
        case 0:
            data = [self.allRows objectAtIndex:[indexPath row]];
            break;
        case 1:
            data = [self.onlySomeRows objectAtIndex:[indexPath row]];
            break;
    }

    //TODO: use data to populate and return a UITableViewCell...
}
0 голосов
/ 16 декабря 2010

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

//int i = 0;
NSMutableArray *rowsToDelete = appDelegate.rowsToDelete;
for(id current in appDelegate.myArray) {
    if([current myTest]) [rowsToDelete addObject:[NSIndexPath ...]];
    //++i;
}
[self.myTableViewController.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationRight];

Если вы используете индекс элемента для создания NSIndexPath, раскомментируйте первую и пятую строки.Также я заметил, что в вашем коде вы начинаете с i = 1.Поскольку NSArrays начинаются с 0, это никогда не удалит первую ячейку.Если вы действительно этого хотите, измените i = 0 на i = 1.

...