Bob*_*ryn 5 uitableview nsfetchedresultscontroller ios
好.这是与此处完全相同的问题:为什么NSFetchedResultsController在设置获取批量大小时加载所有行?
但他的解决方案并不能解决我的问题.
我有一个有几千条记录的屏幕,加载速度很慢.我将批量大小设置为30(大约是屏幕上单元格的三倍),它仍然会循环并由于某种原因加载所有批次.
这是代码
- (NSFetchedResultsController *)guestCardFetchedResultsController
{
if (guestCardFetchedResultsController != nil) {
return guestCardFetchedResultsController;
}
// SELECT * from GuestCard
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"GuestCard" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
// ORDER BY updated DESC
NSSortDescriptor* updatedSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"created" ascending:NO];
[fetchRequest setSortDescriptors:@[updatedSortDescriptor]];
fetchRequest.fetchBatchSize = 30;
NSString *cacheName = self.isReportProblemView ? @"reportProblemGuestCardsAll" : @"guestCardsAll";
[NSFetchedResultsController deleteCacheWithName:cacheName];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:@"sectionIdentifier" cacheName:cacheName];
aFetchedResultsController.delegate = self;
self.guestCardFetchedResultsController = aFetchedResultsController;
// Clean up
NSError *error = nil;
if (![[self guestCardFetchedResultsController] performFetch:&error]) {
}
return self.guestCardFetchedResultsController;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我没有做任何非常有趣的事情.这里是一些委托代码(不包括单元格创建,我只确认了屏幕上的单元格数量):
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if ([self.guestCardFetchedResultsController.fetchedObjects count] == 0) {
return 1;
}
// Return the number of sections.
return [[self.guestCardFetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.guestCardFetchedResultsController.fetchedObjects count] == 0) {
return 1;
}
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [guestCardFetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if ([self.guestCardFetchedResultsController.fetchedObjects count] == 0) {
return @"";
}
return [[self.guestCardFetchedResultsController sections][section] name];
}
Run Code Online (Sandbox Code Playgroud)
在NSFetchedResultsController初始化程序上读取文档之后,我认为问题是您在获取请求(已创建)中有一个排序,它自然地与节键路径(sectionIdentifier)排序相同.我正在查看的文档中的特定句子说:
如果此密钥路径与fetchRequest中第一个排序描述符指定的密钥路径不同,则它们必须生成相同的相对排序
我建议首先修改你的获取请求以对sectionIdentifier进行排序,然后创建.我认为这将解决你的问题.
NSSortDescriptor* updatedSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"created" ascending:NO];
NSSortDescriptor* sectionSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sectionIdentifier" ascending:NO];
// It's critical the sectionSortDescriptor is first
[fetchRequest setSortDescriptors:@[sectionSortDescriptor, updatedSortDescriptor]];
Run Code Online (Sandbox Code Playgroud)
请注意,如果created或者sectionIdentifier属性实际上是实体类的方法,那么肯定会迫使Core Data在排序/分段之前加载所有数据,因为它需要首先在每个实体上执行该方法.
当使用fetchBatchSize而不是返回 NSArray 中的对象时,它返回一个特殊的批处理错误数组。尽管它确实加载了所有对象 ID,但数组中的所有对象都是错误的,这意味着它们的数据未被加载,即像占位符对象。然后,当您在访问对象的属性时循环数组(或重新加载表)时,它会对该对象的属性执行数据库查询,包括直到 fetchBatchSize 的下一个对象(顺便说一下,最小值似乎是 4)。通过查看查询来调试此内部行为的最佳方法是编辑您的方案并添加运行参数:
-com.apple.CoreData.SQLDebug 1
这将输出到控制台各种查询。您将看到行 ID 的第一个查询,然后是每批数据加载。
因此,您可能会遇到加载所有行 ID 和创建故障对象的速度很慢,但这应该很快。
另一种可能性是当它访问 sectionIdentifier 属性来构建部分时,这也会导致对象也被加载,从而导致所有批次都被加载。为了解决这个问题,您可以尝试将 propertiesToFetch 设置为包含 sectionIdentifier,这样第一个查询应该加载到该属性中,然后在访问它时不应该加载该对象。
| 归档时间: |
|
| 查看次数: |
3116 次 |
| 最近记录: |