2013-11-12 3 views
1

Я разработчик Android, работающий над моим первым проектом iOS. У меня есть UITableView, который отображает почти 37 500 строк. Один ряд для каждого предмета в продуктовом магазине. Список содержит 3 столбца, содержащие имя элемента, а остальные 2 содержат другие важные данные. Столбцы сортируются, и для обработки сортировки я сортирую массив данных, как мне нужно, и вызываю [tableView reloadData] после того, как я закончил сортировку массива. Это прекрасно работает, за исключением того, что существует длительная задержка, по крайней мере, через несколько секунд после перезагрузки данных, где основной поток заблокирован, выполняя работу. Я не чужой, чтобы перечислять производительность, поскольку мне приходилось делать плавные списки много раз в Android. Поэтому из того, что я могу сказать, я не очень много делаю, чтобы это сделать. Единственное, о чем я могу думать, это просто большое количество элементов в моем массиве. Вот соответствующий код:Проблема с производительностью UITableView после вызова reloadData

Вот методы табличного я переопределяю:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return [self.data count]; 
} 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
static NSString *simpleTableIdentifier = @"CustomCell"; 
ReplenishListCell *cell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 

if (cell == nil) { 
    cell = [[ReplenishListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; 
} 

NSMutableDictionary *dictData = [self.data objectAtIndex:indexPath.row]; 

cell.nameLabel.text = dictData[@"item-description"]; 
cell.firstLicationColumnLabel.text = dictData[@"store-count"]; 
cell.secondLicationColumnLabel.text = dictData[@"other-count"]; 

return cell; 
} 

-(void)tableView:(UITableView *)replenishTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
[self showActivityIndicator]; 

ReplenishListCell *cell = (ReplenishListCell*) [replenishTableView cellForRowAtIndexPath:indexPath]; 
NSString *nameClicked = cell.nameLabel.text; 

[database getItemByName:nameClicked :self]; 
} 

Вот метод я использую для сортировки массива:

-(void) sortArray:(NSString *) dictionaryKey { 
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:dictionaryKey ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName]; 
NSArray *sortedArray = [data sortedArrayUsingDescriptors:sortDescriptors]; 

[data removeAllObjects]; 
[data addObjectsFromArray:sortedArray]; 

[self.tableView reloadData]; 
} 

я не имеют проблем с производительностью до тех пор, пока не вызывают [self.tableView reloadData]. Поэтому мне интересно, есть ли что-то, чего я не хватает, или, может быть, лучший способ перезагрузить данные, кроме reloadData? Любая помощь будет оценена. Я потратил несколько часов на отладку и Google, и я еще не придумал решение.

+0

Является ли порядок вашего массива важным? –

+0

Вы должны сначала прокомментировать свой код с помощью инструментов и найти фактического виновника. Затем, и только тогда вы можете принять обоснованное решение о том, как подойти к проблеме. – CouchDeveloper

+0

Массив может быть отсортирован пользователем ... поэтому, когда они нажимают кнопку сортировки, тогда заказывайте вопросы –

ответ

1

Ваш код выглядит хорошо. Как @paulrehkugler говорит в своем ответе, вы можете просто сделать data = sortedArray, где вы сортируете массив.

С учетом объема данных у вас есть предварительная сортировка Ваши данные в фоновом режиме. По моим расчетам, с 37 500 объектами потребовалось бы 150 Кбайт памяти, если вы будете хранить около 3 массивов с разными порядками сортировки. Поэтому, когда пользователь выбирает сортировку по определенному столбцу, у вас уже есть сортировка данных, и вы просто замените массив, который используется в качестве источника данных. Для пользователя сортировка тогда будет практически мгновенной.

+0

Учитывая мой проект, я думаю, что это лучшее решение моей проблемы. Большое спасибо всем, кто внес свой вклад. –

1

Одна из возможных причин вашего виджета пользовательского интерфейса заключается в том, что вы удаляете и добавляете все 37.5k объектов между двумя массивами.

Попробуйте это изменить:

[data removeAllObjects]; 
[data addObjectsFromArray:sortedArray]; 

к этому:

data = sortedArray; 
+0

У меня на самом деле было это поначалу. Я получаю эти объекты из другого класса, который извлекает его из веб-базы данных.Объекты попадают в куски, и каждый кусок я должен вызывать '[data addObjectsFromArray: items];' где data - массив, содержащий все объекты, а элементы - это массив с новыми данными, которые будут добавлены к 'data'. вызов 'data = sortedArray' изменяет' data' из измененного массива в обычный массив, что вызывает сбой, потому что обычный массив не имеет метода под названием 'addObjectsFromArray' –

+0

Поскольку' sortedArrayUsingDescriptors' возвращает нормальный массив, а не измененный массив , –

1

Для крупной операции вы должны использовать фоновую очереди, а выполнение, что основной очереди и блокирование пользовательского интерфейса. Вы могли бы назвать reloadData на главной очереди после того, как данные становятся доступными из фоновой операции:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
      [self sortArray:<# your key #>]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.tableView reloadData]; 
    }); 
}); 

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

Смежные вопросы