从asynchronousWeb服务响应更新托pipe对象的最佳方法?

我有一个NSManagedObjectContext关联到主线程( mainContext ),在那里我获取我显示整个应用程序的所有NSManagedObject

用户不要编辑这些对象,但我从Web服务获取更新。 我定期对这些服务执行asynchronous调用,并且“告诉”我要删除哪些pipe理对象(如果有的话),哪些必须用新信息更新(如果有的话),以及是否需要插入新的对象。

所以,我需要首先获得所有服务的响应,然后检查我必须对我的mainContext已有的托pipe对象所做的更改。 而且我还需要执行更新以避免阻止UI。

我正在考虑两种方法来pipe理这种情况:

  1. 在私有队列中使用一个完全独立的privateContext和它自己的核心数据栈来插入所有从服务中获得的对象。 然后以某种方式(如何?)与mainContext的对象进行比较,并删除/修改/插入mainContext对象。
  2. 在专用队列中使用privateContext ,但是作为mainContext的子mainContext 。 然后,我需要传递子对象的父对象mainContext中的对象(这是可能的?如何?),同时在这个子对象中插入从服务获得的对象,然后比较和执行更改。

哪些方法是最好的或适当的? 或者,也许应该是一个我没有想过的不同的?

提前致谢

编辑:这可能是另一种可能的方式?

  1. 只使用mainContext ,而我正在parsing服务的响应,而不是创build新的对象,只需要在mainContext逐一进行更改…

编辑2:另一种可能性?

  1. 只有使用privateContext ,获取服务响应并创build新的对象。 然后,也可以用这个privateContext获取所有已经存在的对象(和mainContext的对象一样)。 在这个privateContext比较两组对象(最近创build的服务和获取的),保存此上下文,清除mainContext并重新获取mainContext所有对象。

我不确定这是一个完整的答案,但我正在做一个类似的情况。 我所采取的实现path是使用子对象(遍布整个地方) – 或者更像是需要的临时子上下文。

我应该提到的第一件事是确保将CoreDatadebuggingfunction内置到XCOde中。 我做了第二个跑步计划

-com.apple.CoreData.ConcurrencyDebug 1

在这里输入图像说明

在应用程序初始化我有我的正常的NSManagedObjectContext – 这是传递到我的后台networking线程。

 NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [child setParentContext:parentObjectContext]; 

然后,无论何时我需要传递一些从父母到孩子的事情,我最终都会做:

 [child objectWithID:(object-in-parent-context)] 

或者我最终在做

 __block AHRS_RPYL * ret; [[self getChildContext] performBlockAndWait:^{ ret = [NSEntityDescription insertNewObjectForEntityForName:@"RPYL" inManagedObjectContext:[self getChildContext]]; // ... lots of code }]; 

我不能说我真的“喜欢”这个方法,而且我暂时坚持这个方法,但它确实工作得很好。

在我的大多数视图控制器之间,我有一个

 @synthesize managedObjectContext; 

在我的prepareForSegue方法

 // Pass on managedObjectContext - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // dispatch_async(dispatch_get_main_queue(), ^{ // If the destination VC is able to take teh setManagedObjectContext method the current objectContext will be passed along. if ([segue.destinationViewController respondsToSelector:@selector(setManagedObjectContext:)]) { [segue.destinationViewController performSelector:@selector(setManagedObjectContext:) withObject:self.managedObjectContext]; } else { NSLog(@"Segue to controller [%@] that does not support passing managedObjectContext", [segue destinationViewController]); } // }); } 

概要

  • 我已经与你的第二select的select,这是可行的,虽然它在我的诚实的意见感觉有点笨拙。 事实是,我们正在考虑切换到Realm而不是CoreData因为不pipe你怎么看它, CoreData都不是最易于使用的选项。

UDPATES

保存代码

我实际上每50条消息就会保存到子上下文中,并且每隔250个字符就会保存到父项(在年龄上并没有触及这个代码)。 我不能保证这是做最好的正确的方式,但它确实工作,它确保光盘访问最小。 我得到了很多消息像20+秒,所以我想要做这个堆栈types。 你可能不在乎

(self.getChild())返回子上下文 – 我留在这里的旧代码。

 if (msgCount % 50 == 0) { // Child Save! // NSLog(@"Saving SDatas"); __block NSManagedObjectContext *currentChild = [self getChildContext]; [self incChildContext]; // Parent-Child save methodology [currentChild performBlock:^{ NSError *error; if (![currentChild save:&error]) { NSLog(@"\n error => %@ \n", [error localizedDescription]); NSLog(@" error => %@ ", [error userInfo]); [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; // abort(); } if (msgCount % 250 < 5) { [parentObjectContext performBlock:^{ NSError *error; if (![parentObjectContext save:&error]) { NSLog(@"\n error => %@ \n", [error localizedDescription]); NSLog(@" error => %@ ", [error userInfo]); [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; // abort(); } }]; } [currentChild reset]; }]; } 

删除

  [childContext performBlock:^{ // LOTS OF CODE // to build a query set of the records we want to kill // End lots of code [childContext deleteObject:msg]; if (i % modFactor == 0) { self.percentDone = i / totalRecords; NSLog(@"%.1f Saving ...", self.percentDone * 100); NSError *error; if (![childContext save:&error]) { NSLog(@"\n error => %@ \n", [error localizedDescription]); NSLog(@" error => %@ ", [error userInfo]); [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; // abort(); } [parentContext performBlock:^{ NSError *errrror; if (![parentContext save:&errrror]) { NSLog(@"\n error => %@ \n", [error localizedDescription]); NSLog(@" error => %@ ", [error userInfo]); [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; // abort(); } }]; } }]; 

再次 – 就像我之前所说,这可能不是做事的最佳方式,但我有一个父/子堆栈,它的工作。 这是我写的第一个iOS应用程序之一,并再次做我会踢核心数据和使用别的东西。

我们有一个非常高的更新率,所以当我们使用一个单一的堆栈,使得用户界面非常缓慢。 迁移到父母/孩子是慢的 – 我再次这样做,我认为它会更顺利,因为我会写很多帮助函数来处理一些(或只是使用迅速)。

祝你好运。