【问题标题】:Tableview loading slow表格视图加载缓慢
【发布时间】:2012-04-03 09:10:41
【问题描述】:

我的 tableview 的加载时间有问题,我该如何改进?加载大约 90000+ 行的 tableview 大约需要 25-30 秒。我的 sqlite 数据库中有大约 130000 行,我使用核心数据访问这些数据。

任何帮助或建议将不胜感激。

感谢您抽出宝贵时间,如果您需要更多信息,请告诉我。

我一直在努力优化两件事。

+核心数据 - 也许我的数据获取可以改进,但我不知道我还能做什么,代码如下。

if (fetchedResultsController != nil) 
{
    return fetchedResultsController;
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"DataModel" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"subsection" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

//[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"section == [c] %@ AND area == 'Tables'", tablesSection]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"area == 'Tables'"]];

[fetchRequest setFetchBatchSize:100];
//[fetchRequest setFetchLimit:100];
[fetchRequest setFetchOffset:10];

NSFetchedResultsController *theFetchedResultsController = 
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:@"uppercaseFirstLetterOfNameTables" cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
fetchedResultsController.delegate = self;

return fetchedResultsController;    

+tableview,我认为我加载数据的方式可能是这里的主要问题。我动态计算每个单元格的高度,我认为这会减慢速度,如果我删除方法 heightForRowAtIndexPath 的代码,我可以将加载时间缩短到 8 秒。

(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Model *info;
    if(self.searchDisplayController.isActive)
    {
        info = [searchFetchedResultsController objectAtIndexPath:indexPath];
    }
    else
    {
        info = [fetchedResultsController objectAtIndexPath:indexPath];
    }
    NSString *subsectionHeight = info.subsection;
    NSString *textHeight = info.text;
    CGSize titleSize = [subsectionHeight sizeWithFont:[UIFont fontWithName:@"Helvetica-Bold" size:20] constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
    CGSize detailSize = [textHeight sizeWithFont:[UIFont fontWithName:@"Helvetica-Bold" size:16] constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];

    return detailSize.height+titleSize.height;

    //return 88;
}



 (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        cell.detailTextLabel.numberOfLines = 0;
    }
    //if-statement need to prevent search index issue
    if(self.searchDisplayController.isActive && [self.searchDisplayController.searchBar.text isEqualToString:@""])
    {
        return cell;
    }
    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

 (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{
    Model *info;
    if (self.searchDisplayController.isActive)
    {
        info = [searchFetchedResultsController objectAtIndexPath:indexPath];
    }
    else
    {
        info = [fetchedResultsController objectAtIndexPath:indexPath];
    }
    cell.textLabel.text = info.subsection;
    cell.detailTextLabel.text = info.text;

}

更新:我正在使用注释掉 heightForRowAtIndexPath 的解决方案,但我需要搜索优化方面的帮助,有人可以帮助我了解如何在 WWDC 2010 session 137 Optimizing Core Data Performance 中实施该解决方案,我不明白创建新实体部分,例如我需要用数据填充那个新实体吗?

【问题讨论】:

  • 90000+ 行对于单个表视图来说是荒谬的。没有人能够滚动到最后。将您的数据分成多个部分并具有导航结构。
  • 我同意单个 tableview 的 90000+ 行是疯狂的,但不幸的是这是给我的,我很想分解数据,但我不知道如何做到这一点,因为它的 SAP 表数据。

标签: ios uitableview core-data


【解决方案1】:

你必须为你的 tableview 分页:在 tableview 的末尾放置一个显示更多结果的按钮 (我无法想象自己在 9000 行上滚动)

【讨论】:

【解决方案2】:

您绝对不需要调用 heightForRowAtIndexPath 9000 次,只需将 IB 中的高度设置为您需要的高度并将该方法取出即可。 9000 条记录的 8 秒实际上并没有那么糟糕。

9000 条记录对于 TableView 来说是很多需要处理的。无论如何你可以减少这个#?

【讨论】:

  • 我想把数据分成几类,可惜我不知道怎么做,我对数据不熟悉。
  • 如果去掉那个 heightForRow 方法,加载时间是多少?当我说删除它时,我的意思是注释掉整个方法并在 IB 中设置单元格高度。
  • 如果我注释掉 heightForRow,加载大约需要 8 秒。这就是我目前的工作。
  • 真的没有那么糟糕。我有一个从数组填充的 TableView(从 web 服务读取),获取所有数据并填充电视大约需要 6-8 秒。我为屏蔽加载所做的一件事是显示一个身份验证对话框,以便在用户登录时加载电视。
【解决方案3】:

如果您需要填充 UITableViewCell 的只是属性“文本”和“子部分”,那么您可以将主表拆分为一个只有这两个属性和一个关键字段的表,然后将所有其他属性放在另一个表,一对一链接。 如果所有记录都被读入内存(当您启动 UITableview 时通常不会发生这种情况),那么如果表更小(即只包含几列)将花费更少的时间。我将一个图像字段从主表中移出,同时在主表中保留了大约 5 个字段和 5 个关系,并且在 iPad 2 上对 150.000 条记录没有任何问题。

但您应该通过记录 Core Data 正在使用的实际 SQL 语句来测试实际发生的情况(通过在启动时将 -com.apple.CoreData.SQLDebug 1 作为参数传递)。

如果您的应用运行良好,则只有最初显示的记录应该触发 heightForRowAtIndexPath 方法。所以不是 130.000 次,而是最多。 10 次显示第一个结果。所以这通常不是你的问题。

分页也是一种解决方案。但在正常情况下,核心数据会在幕后自动处理分页。只需设置 fetchBatchSize 就足以让它自动发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 2022-01-20
    • 2018-10-17
    • 1970-01-01
    相关资源
    最近更新 更多