ios – CoreData子上下文,NSFetchedResultsController和主线程

ios – CoreData子上下文,NSFetchedResultsController和主线程,第1张

概述在Olivier Drobnik的 this excellent post之后,我实现了CoreData大师Marcus S. Zarra提出的三层CoreData堆栈: 与此图和我的代码的唯一区别是我只使用一个临时背景MOC,以避免在几个临时MOC中插入对象时出现重复.这是我的上下文初始化代码: #pragma mark - NSManagedObjectContexts+ (NSManag 在OlivIEr Drobnik的 this excellent post之后,我实现了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 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;}

这段代码非常简单.我只使用NSMainQueueConcurrencyType中的mainUIManagedobjectContext复制上面的图表.每次保存子上下文importManagedobjectContext时,都会触发通知,并且所有父上下文都会在其当前线程中执行保存.

我已经实现了一个带有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];}

在这里,我将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];    }];}

问题是,我正在插入5000个对象,当数据填充到表视图中时,UI正在冻结. Florian Kugler ran a test with this architecture插入15.000个对象并使用乐器获得此主线程用法(蓝色表示主线程,灰色表示任何其他线程):

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

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

解决方法 是的,这是预期的,因为主要的MOC参与其子女的拯救.当UI上下文的孩子不进行大的保存时,这很方便,也很好,但如果这些保存更大,则常常会成为性能问题.使用此模式时,无法确定UI线程仅执行最小作业.

对于大型保存,我建议创建一个直接使用持久性存储协调器配置的上下文.发生大保存后,您只需在UI上下文中重新获取并可选地刷新数据.有关详细信息,请参阅我的答案here.

总结

以上是内存溢出为你收集整理的ios – CoreData子上下文,NSFetchedResultsController和主线程全部内容,希望文章能够帮你解决ios – CoreData子上下文,NSFetchedResultsController和主线程所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1055253.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存