amb*_*amb 4 multithreading core-data objective-c nsmanagedobjectcontext ios
在Olivier Drobnik的这篇优秀文章之后,我实现了CoreData大师Marcus S. Zarra提出的三层CoreData堆栈:

与此图和我的代码的唯一区别是我只使用一个临时背景MOC,以避免在几个临时MOC中插入对象时出现重复.这是我的上下文初始化代码:
#pragma mark - NSManagedObjectContexts
+ (NSManagedObjectContext *)privateManagedObjectContext
{
if (!_privateManagedObjectContext) {
// Setup MOC attached to PSC
_privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateManagedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
// Add notification to perform save when the child is updated
_privateContextSaveObserver =
[[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSManagedObjectContext *savedContext = [note object];
if (savedContext.parentContext == _privateManagedObjectContext) {
[_privateManagedObjectContext performBlock:^{
NSLog(@"AMBCoreData -> saving privateMOC");
NSError *error;
if (![_privateManagedObjectContext save:&error]) {
NSLog(@"AMBCoreData -> error saving _privateMOC: %@ %@", [error localizedDescription], [error userInfo]);
}
}];
}
}];
}
return _privateManagedObjectContext;
}
+ (NSManagedObjectContext *)mainUIManagedObjectContext
{
if (!_mainUIManagedObjectContext) {
// Setup MOC attached to parent privateMOC in main queue
_mainUIManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainUIManagedObjectContext setParentContext:[self privateManagedObjectContext]];
// Add notification to perform save when the child is updated
_mainUIContextSaveObserver =
[[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSManagedObjectContext *savedContext = [note object];
if (savedContext.parentContext == _mainUIManagedObjectContext) {
NSLog(@"AMBCoreData -> saving mainUIMOC");
[_mainUIManagedObjectContext performBlock:^{
NSError *error;
if (![_mainUIManagedObjectContext save:&error]) {
NSLog(@"AMBCoreData -> error saving mainUIMOC: %@ %@", [error localizedDescription], [error userInfo]);
}
}];
}
}];
}
return _mainUIManagedObjectContext;
}
+ (NSManagedObjectContext *)importManagedObjectContext
{
if (!_importManagedObjectContext) {
// Setup MOC attached to parent mainUIMOC in private queue
_importManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_importManagedObjectContext setParentContext:[self mainUIManagedObjectContext]];
}
return _importManagedObjectContext;
}
Run Code Online (Sandbox Code Playgroud)
这段代码非常简单.我只使用mainUIManagedObjectContext中的复制上面的图表NSMainQueueConcurrencyType.每次importManagedObjectContext保存子上下文时,都会触发通知,并且所有父上下文都会在其当前线程中执行保存.
我已经实现了一个带有a UITableView和NSFetchedResultsController附加的测试视图控制器.这是viewDidLoad我的测试视图控制器中的代码:
- (void)viewDidLoad
{
[super viewDidLoad];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Task"];
[request setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"insertDate" ascending:NO]]];
self.fetchRequest = request;
NSFetchedResultsController *frc =
[[NSFetchedResultsController alloc]
initWithFetchRequest:self.fetchRequest
managedObjectContext:[AMBCoreData mainUIManagedObjectContext]
sectionNameKeyPath:nil
cacheName:nil];
frc.delegate = self;
[self setFetchedResultsController:frc];
[self.fetchedResultsController performFetch:nil];
}
Run Code Online (Sandbox Code Playgroud)
在这里,我附上mainUIManagedObjectContext了NSFetchedResultsController.后来,在我的viewDidAppear运行循环中插入了几个Task实体:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[AMBCoreData importManagedObjectContext] performBlock:^{
for (int i = 0; i < 5000; i++) {
Task *task = [NSEntityDescription insertNewObjectForEntityForName:@"Task" inManagedObjectContext:[AMBCoreData importManagedObjectContext]];
task.title = [NSString stringWithFormat:@"Task %d", i];
task.insertDate = [NSDate new];
[[AMBCoreData importManagedObjectContext] save:nil];
}];
}
Run Code Online (Sandbox Code Playgroud)
问题是,我正在插入5000个对象,当数据填充到表视图中时,UI正在冻结.Florian Kugler 用这个架构进行了测试,插入了15.000个对象和乐器,他得到了这个主线程用法(蓝色用于主线程,灰色用于任何其他线程):

但这是我的主要线程CPU使用5000个对象,使用iPhone 5进行分析:

正如您所看到的,我的主要线程使用量远远大于Florian的,并且我的UI冻结了几秒钟.我的问题是,我做错了什么?这是使用这个三层MOC架构a NSFetchedResultsController和a 时的预期行为UITableView吗?我知道插入5000个对象并不是大多数应用程序的常用行为,所以当我尝试使用50或100个对象时,冻结是不存在或不明显的,但主线程使用率很高(尽管我承认在这种情况下它可以是因为其他原因,如唤醒应用程序).
| 归档时间: |
|
| 查看次数: |
2527 次 |
| 最近记录: |