1

I'm an Android developer working on my first iOS project. I have a UITableView that displays almost 37,500 rows. One row for each item in an grocery store. The list has 3 columns one containing the item name and the other 2 containing other important data. The columns are sortable, and to handle the sorting I sort the data array as I need to and call [tableView reloadData] after I'm done sorting the array. This works fine except there is a long delay of at least a few seconds after reloading the data where the main thread is locked up doing work. I'm no stranger to list performance as I've had to make smooth lists numerous times in Android. So from what I can tell I'm not really doing much to cause this. The only thing I can think of is just the large number of items in my array. Here is the relevant code:

Here are the table methods I am overriding:

-(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];
}

Here is the method I use to sort the array:

-(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];
}

I do not have any performance issues until after calling [self.tableView reloadData]. So I'm wondering if there is something I'm missing, or is there maybe a better way of reloading the data besides reloadData? Any help will be greatly appreciated. I've spent a few hours now debugging and Googling and I haven't come up with a solution yet.

4

3 回答 3

1

对于大型操作,您应该使用后台队列,而不是在主队列和阻塞 UI 上执行。在后台操作提供数据后,您可以在主队列上调用 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];
    });
});

还可以考虑使用 Paul 的建议,如上一个答案所示。

于 2013-11-12T21:44:30.680 回答
1

你的代码看起来不错。就像@paulrehkugler 在他的回答中所说的那样,您可以data = sortedArray在对数组进行排序的地方进行操作。

根据您拥有的数据量,考虑在后台线程中对数据进行预排序。根据我的计算,如果您保留大约 3 个具有不同排序顺序的数组,则使用 37,500 个对象将需要 150K 的内存。因此,当用户选择按特定列排序时,您已经对数据进行了排序,您只需交换用作数据源的数组即可。对于用户来说,排序几乎是瞬间完成的。

于 2013-11-12T21:46:25.183 回答
1

您的 UI 挂起的一个可能原因是您正在删除和添加两个数组之间的所有 37.5k 对象。

尝试改变这个:

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

对此:

data = sortedArray;
于 2013-11-12T21:36:31.817 回答