2014-09-26 24 views
0

我有一个应用程序,将数据同步到服务器。这个过程是: 1)将本地数据转换为JSON 2)通过HTTP Post发送本地数据到服务器 3)处理来自服务器的来自HTTP Post的响应2)-0,即它的确认表单服务器它没有它的处理,并保存一切OK 4)执行从服务器作业的JSON HTTP请求更新 5)处理这个JSON保存到核心数据正确的方式来处理HTTP POST,然后通过HTTP下载,然后保存到核心数据

我试图把各个部分在后台线程,所以我可以释放UI。我一直有间歇性问题,我认为这是因为我在后台线程上使用核心数据。

这个过程是从一个按钮点击开始的,所以为了让UI工作,我需要在后台线程中至少做一些操作。

目前我发送初始方法调用到后台线程,并在后台处理它,更新主线程上的进度信息的用户界面。

我可以保持原样,但强制核心数据部分到主线程?那是一个很好的解决方案吗?将所有内容保留在后台并将核心内核数据位放回主线程是否可行?

谢谢!

编辑 - 我现在已经使代码更明智 - VC现在将处理启动到后台线程,并通过3个用于发送和下载数据的类的协议调用更新UI。

每个类都有它自己的管理对象上下文对象,但每类使用下面的代码来初始化:

-(NSManagedObjectContext*) managedObjectContext 
{ 
    if (!_managedObjectContext) 
    { 
     mavisFireChecksAppDelegate *appDelegate = (mavisFireChecksAppDelegate *) [[UIApplication sharedApplication] delegate]; 
     _managedObjectContext=appDelegate.managedObjectContext; 

    } 
    return _managedObjectContext; 
} 

我应该改变呢?这些类是在后台线程上创建的,尽管它们停留在该线程上,appdeleegate.managedObjectContext是在应用程序加载时创建的,所以在主线程上也是这样。我现在有这个正确的东西吗?这三个类应该都会初始化一个新的MOC,因为它们在后台运行时不使用appDelegate托管对象上下文,并且在主线程上创建应用程序委托?

没有实际改变被管理对象的上下文init不是类,它仍然每隔50-100次调用一次就出错一次。使用appldelegate.managedobject的背景对象的问题

编辑****的可能原因

在下面线程接受的解决方案,但任何人一些额外的有用的信息阅读本:

我只是想增加其他人阅读它的时间。我确实把所有的CD调用都包含在了perform块中,但是引入了一个新的错误,因为我没有在2个单独的MOC上正确地合并这些更改。由daniel提供的链接 - robots.thoughtbot.com/core-data

,是辉煌的,并表明我的错误。还有一个CD堆栈,您可以从文章底部链接git hub。

+0

总是在后台线程执行的核心数据。你是否将所有的核心数据调用封装在一个上下文perfomBlock中:? – 2014-09-26 14:02:33

+0

看看Magical Record,他们简化了核心数据中所需的大量锅炉板,并且他们真的为执行所有CD操作提供了一个有用的API https://github.com/magicalpanda/MagicalRecord – 2014-09-26 14:04:40

+0

感谢您的答复。这个项目戏剧性地改变了范围,虽然我意识到CD不是线程安全的,因为我原来并没有使用线程,我没有多少关注它。 我还没有使用performBlocks。我现在必须正确地看这个。 导入/导出例程有两个部分,一个是它自己的类,它有自己的托管对象上下文,另一个在视图控制器中将其踢出(我认识的设计不好)。这就是间歇性错误。我不认为我在主线上创建了MOC,但我会先检查它! – 2014-09-29 07:58:29

回答

1

从后台线程调用核心数据并不意味着你已经实现了并发。考虑下面的代码创建一个后台线程上下文:

- (NSManagedObjectContext *)createBackgroundContextWithStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator {   
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [context setPersistentStoreCoordinator:coordinator]; 
    context.undoManager = nil;//if you don't need an undo manager always do this for performance boosts 
    return context; 
} 

你将看到上下文有NSPrivateQueueConcurrencyType并发类型,而你的用户界面的东西通常有NSMainQueueConcurrencyType

现在,你有你应该后台前后请注意performBlock:(异步)和performBlockAndWait:(同步)调用与Core Data进行交易。所以你的导入过程可能是这样的:

- (void)importStuff:(NSArray *)stuffToImport 
     usingContext:(NSManagedObjectContext *)context 
    andPerformBlock:(void (^)(BOOL madeChanges))completionBlock { 
    [context performBlock:^{ 
     /** 
     * do some import stuff 
     */ 
     BOOL madeChanges = [context hasChanges]; 
     [context save:nil]; 
     if (completionBlock) { 
      completionBlock(madeChanges); 
     } 
    }]; 
} 

,你会调用导入方法如下:

NSArray *stuff = //whatever you fetched from server; 
NSManagedObjectContext *context = //background context; 
[importer importStuff:stuff 
     usingContext:context 
     andPerformBlock:^(BOOL madeChanges){ 
     if (madeChanges){ 
      //reload UI 
     } 
}]; 

记住,管理对象是线程安全的。您应该始终确保执行任何更新,访问或插入到上下文performBlock或performBlockAndWait中。

一般来说,我发现,块进口更多有用的比委托方法:)

导入数据时
+0

谢谢,这一切都有所帮助。我也一直在阅读苹果文档。我想我现在全部了解。 最后一个问题 - 我去查看一个工作是否已经存在,然后更新或插入。作业对象中有很多子对象。你会用一个大块还是很多小块?我总是喜欢问建议:) 顺便说一下 - 核心数据编程指南 - 并发指南https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/Articles/cdConcurrency.html# // apple_ref/doc/uid/TP40003385-SW1 实际上他说最好的做法已经改变了,让我困惑! – 2014-09-29 13:49:17

+0

我刚看到那个,很不幸!我想浏览网页,看http://robots.thoughtbot.com/core-data和http://floriankugler.com/blog/2013/4/2/the-concurrent-core-data-stack – 2014-09-29 13:56:23

+0

我只是想增加其他人阅读它的时间。我确实把所有的CD调用都包含在了perform块中,但是引入了一个新的错误,因为我没有在2个单独的MOC上正确地合并这些更改。 daniel提供的链接 - http://robots.thoughtbot。com/core-data,非常出色,并向我展示了我的错误。还有一个CD堆栈,您可以从文章底部链接git hub。 – 2014-09-30 13:58:38

相关问题