核心数据sectionNameKeyPath与关系属性性能问题 [英] Core Data sectionNameKeyPath with Relationship Attribute Performance Issue
问题描述
我有一个有三个实体的核心数据模型:
Person
, Group
照片
之间的关系如下:
- 人< --------->群组(一对多关系)
- 人物<------------->相片(一对一)
当使用 NSFetchedResultsController
$ c> UITableView ,我想使用 Group
在 Person
为此,我使用 sectionNameKeyPath:@group问题是当我使用
组$ c>中的属性时, $ c>关系,
NSFetchedResultsController
以小批量20(我有 setFetchBatchSize:20
)提取所有内容在我滚动 tableView
时抓取批次。
如果我使用 Person
实体(如 sectionNameKeyPath:@name
)创建部分一切正常: NSFetchResultsController $
我用来实例化NSFetchedResultsController的代码:
- (NSFetchedResultsController *)fetchedResultsController {
if(_fetchedResultsController){
return _fetchedResultsController;
}
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:[Person description]
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
//指定如何对获取的对象进行排序
NSSortDescriptor * groupSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@group.name
ascending:YES];
NSSortDescriptor * personSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@birthName
ascending:YES
selector:@selector(localizedStandardCompare :)];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:groupSortDescriptor,personSortDescriptor,nil]];
[fetchRequest setRelationshipKeyPathsForPrefetching:@ [@group,@photo]];
[fetchRequest setFetchBatchSize:20];
NSError * error = nil;
NSArray * fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:& error];
if(fetchedObjects == nil){
NSLog(@Error Fetching:%@,error);
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:@group.namecacheName:@masterCache];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
这是我在乐器中获得的,如果我创建基于group.name
,无需与应用程序界面进行任何交互:
这是我得到的(在UITableView上滚动一下)如果sectionNameKeyPath是nil:
< img src =https://i.stack.imgur.com/46WIt.pngalt =没有任何部分的核心数据提取>
请任何人帮助我解决这个问题?
编辑1:
我从模拟器和仪器得到不一致的结果:当我提出这个问题,应用程序是在模拟器中启动大约10秒(通过Time Profiler)使用上述代码。
但是今天,使用与上面相同的代码,应用程序在模拟器中启动900毫秒,即使它对所有对象进行临时预取,它不阻塞UI。
我附上了一些新的屏幕截图:
< img src =https://i.stack.imgur.com/RaaUF.pngalt =在滚动和小批量抓取模拟器中进行预取>
编辑2:
我重置模拟器,结果很有趣:执行导入操作并退出应用程序后,第一次运行如下所示:
滚动一下后:
现在这是在第二次运行发生:
第五次运行后:
编辑3:
第七次运行应用程序和八次,我得到这个:
自从我发布了这个问题,我终于找到了启用此行为的罪魁祸首(在Xcode 6中稍有改变):
-
关于不一致的获取时间:我使用缓存,当我来回打开,关闭和重置模拟器时。
-
setFetchBatchSize
似乎不能与父/子上下文 code>。该问题在2012年已回报,似乎仍然存在 http://openradar.appspot.com/11235622。
为了克服这个问题,我用 有关问题#2的详情,请访问: http://stackoverflow.com/a / 11470560/1641848 I have a Core Data Model with three entities: When I perform a fetch using the For that, I use The problem is that when I'm using the attribute from the If I use an attribute from the The code I use to instantiate the NSFetchedResultsController: This is what I get in Instruments if I create sections based on And this is what I get (with a bit of scrolling on UITableView) if sectionNameKeyPath is nil:
Please, can anyone help me out on this issue? EDIT 1: It seems that I get inconsistent results from the simulator and Instruments: when I've asked this question, the app was starting in the simulator in about 10 seconds (by Time Profiler) using the above code. But today, using the same code as above, the app starts in the simulator in 900ms even if it makes a temporary upfront fetch for all the objects and it's not blocking the UI. I've attached some fresh screenshots:
EDIT 2:
I reset the simulator and the results are intriguing: after performing an import operation and quitting the app the first run looked like this:
After a bit of scrolling:
Now this is what happens on a second run:
After the fifth run:
EDIT 3:
Running the app the seventh time and eight time, I get this:
After almost a year since I've posted this question, I've finally found the culprits that enable this behaviour (which slightly changed in Xcode 6): Regarding the inconsistent fetch times: I was using a cache and at the time I was back and forth with opening, closing and resetting the simulator. Regarding the fact that everything was fetched upfront in small batches without scrolling (in Xcode 6's Core Data Instruments that's not the case anymore - now it's one, big fetch which takes entire seconds): It seems that To overcome this issue, I created another More about issue #2 here: http://stackoverflow.com/a/11470560/1641848 这篇关于核心数据sectionNameKeyPath与关系属性性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! NSMainQueueConcurrencyType创建了另一个
独立上下文
c>并将其持久性协调器
设置为与其他上下文
正在使用的相同。 / p>
Person
, Group
, Photo
with relationships between them as follows:
NSFetchedResultsController
in a UITableView
, I want to group in sections the Person
objects using the Group
's entity name
attribute.sectionNameKeyPath:@"group.name"
.Group
relationship, the NSFetchedResultsController
fetches everything upfront in small batches of 20 (I have setFetchBatchSize: 20
) instead of fetching batches while I'm scrolling the tableView
.Person
entity (like sectionNameKeyPath:@"name"
) to create sections everything works OK: the NSFetchResultsController
loads small batches of 20 objects as I scroll.- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[Person description]
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Specify how the fetched objects should be sorted
NSSortDescriptor *groupSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"group.name"
ascending:YES];
NSSortDescriptor *personSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthName"
ascending:YES
selector:@selector(localizedStandardCompare:)];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:groupSortDescriptor, personSortDescriptor, nil]];
[fetchRequest setRelationshipKeyPathsForPrefetching:@[@"group", @"photo"]];
[fetchRequest setFetchBatchSize:20];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(@"Error Fetching: %@", error);
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"group.name" cacheName:@"masterCache"];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
"group.name"
without any interaction with the App's UI:
setFetchBatchSize
does not work correctly with parent/child contexts
. The issue was reported back in 2012 and it seems that it's still there http://openradar.appspot.com/11235622.independent context
with an NSMainQueueConcurrencyType
and set its persistence coordinator
to be the same that my other contexts
are using.