【发布时间】:2011-04-17 07:43:36
【问题描述】:
在模型中,我有两个实体:Record 和 Category。类别通过反向关系与记录一对多。持久化存储是 SQLITE 类型,db 也不算小,大约 23MB(17k 条记录)。
我使用列表详细设计来显示记录表和详细记录视图。列表视图控制器使用 NSFetchedResultsController。
在设备上构建,如果我不使用 setFetchBatchSize:
CoreData:注解:sql连接获取时间:15.8800s CoreData:注释:总提取执行时间:16.9198 秒,17028 行。
天哪!
如果我使用 setFetchBatchSize:25,一切都会再次正常运行:
CoreData:注解:sql连接获取时间:1.1736s CoreData:注释:总提取执行时间:1.1900 秒,17028 行。
是的,那太好了!但事实并非如此!在列表 viewController 中,当用户点击记录时,我会分配一个详细的 viewController,并在 fetchedResultsController 中的 indexPath 处传递记录:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Record *record = (Record *)[fetchedResultsController objectAtIndexPath:indexPath];
RecordViewController *recordViewController= [[RecordViewController alloc] init];
recordViewController.record = record;
[self.navigationController pushViewController:recordViewController animated:YES];
[recordViewController release];
}
现在,在详细的 viewController 中,我有一个按钮可以将记录设置为收藏或不收藏:
- (IBAction) setFavorite {
if (![record.ISFAV intValue])
[record setValue:[NSNumber numberWithInt:1] forKey:@"ISFAV"];
else
[record setValue:[NSNumber numberWithInt:0] forKey:@"ISFAV"];
###SAVE ON THE CONTEXT HERE###
}
好的,你准备好了吗?如果我点击列表中的第一条记录,然后从收藏夹中添加或删除它,它会在 0.0046 秒内立即发生!带有 SQL 调试模式的控制台仅显示 UPDATE 语句:
CoreData: sql: BEGIN EXCLUSIVE CoreData: sql: UPDATE ZRECORD SET ZISFAV = ?, Z_OPT = ?在哪里 Z_PK = ?和 Z_OPT = ? 核心数据:sql:提交 CoreData:注解:sql执行时间:0.0046s
如果我快速滚动大列表(我显然在控制台上找到了批处理请求),当我点击一个包含许多批处理请求的记录并从收藏夹中添加\删除它时,很多很多很多(太多!我滚动的越多,它们就越多!)SELECT 语句出现在控制台中,位于 UPDATE 语句之前。这意味着总执行时间不可接受(uibutton 在 iphone 上冻结了很长时间)。
发生了什么事?该问题显然与批量获取请求有关。更多 fetch 请求 = 在 UPDATE 语句之前有更多 SELECT 语句。这是其中之一:
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCONTENT, t0.ZCONTENT2, t0.ZISUSER, t0.ZISFAV, t0.ZTITLE, t0.ZTITLE2, t0.ZID, t0 .ZAUTHOR, t0.ZCATEGORY FROM ZRECORD t0 WHERE t0.Z_PK IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?,?,?) ORDER BY t0.ZTITLE LIMIT 26
如果我删除 setFetchBatchSize,没有问题(但启动需要 16 秒)。似乎当我更新属性 ISFAV 时,CoreData 需要再次执行到达该记录所需的所有 fetchRequests,即使我将该记录作为对象传递给详细视图控制器。
抱歉,这篇文章太长了,我尽量说得更清楚。 非常感谢,我快把自己逼疯了……
【问题讨论】:
-
让用户滚动浏览 17,000 行的表格是糟糕的设计,以至于您的用户会想要私刑。想象一下,在繁忙的人行道上用拇指滚动时,试图从 17,000 行中找到一行。您需要将其分解为表格的层次结构,以便点击三到四次将用户带到最多只有一百行左右的列表。这也将使您的表现更易于管理。
标签: iphone performance core-data nsfetchedresultscontroller