gpt4 book ai didi

ios - 处理HTTP Post,然后通过HTTP下载,然后保存到核心数据的正确方法

转载 作者:行者123 更新时间:2023-11-29 02:38:34 39 4
gpt4 key购买 nike

我有一个应用程序可以将数据同步到服务器。过程是:1)将本地数据转换为JSON2) 将本地数据以 HTTP Post 的形式发送到服务器3) 在 2) -0 中处理来自 HTTP Post 的服务器响应,即它是服务器的确认表单,它正在处理它,并保存了一切 OK4) 从服务器对 JSON 进行 HTTP 请求以进行作业更新5)处理这个JSON保存到核心数据

我试过将各个部分放在后台线程上,这样我就可以发布 UI。我一直遇到间歇性问题,我认为这是因为我在后台线程上使用核心数据。

此过程从单击按钮开始,因此为了保持 UI 正常工作,我至少需要在后台线程中执行一些操作。

目前我将初始方法调用发送到后台线程,并在后台处理所有这些,在主线程上使用进度消息更新 UI。

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

谢谢!

编辑 - 我现在使代码更合理 - VC 现在开始处理后台线程,并通过来自 3 个用于发送和下载数据的类的协议(protocol)调用更新 UI。

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

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

}
return _managedObjectContext;
}

我应该改变这个吗?这些类是在后台线程上创建的,尽管它们保留在该线程上,但 appdeleegate.managedObjectContext 是在应用程序加载时创建的,因此在主线程上创建。我现在脑子里有这个正确的吗?这 3 个类都应该初始化一个新的 MOC,而不是使用 appDelegate 托管对象上下文,因为它们在后台运行,并且应用程序委托(delegate)是在主线程上创建的?

在没有实际更改托管对象上下文初始化而不是类的情况下,它仍然每 50-100 次调用左右出错一次。在后台对象中使用 appldelegate.managedobject 可能是问题的原因

编辑****

在下面的线程中接受了解决方案,但对于阅读本文的任何人来说还有一些有用的信息:

我想补充一点,以防其他人读到它。我确实将所有 CD 调用包装在 perform... block 中,但引入了一个新错误,因为我没有在 2 个单独的 MOC 上正确合并更改。丹尼尔提供的链接 -robots.thoughtbot.com/core-data

,非常棒,让我看到了我的错误。还有一个 CD 堆栈,您可以从本文底部链接的 git hub 中提取它。

最佳答案

从后台线程调用Core Data并不意味着你已经实现了并发。考虑以下创建后台线程上下文的代码:

- (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 的并发类型,而您的 UI 内容通常具有 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 中执行任何更新、访问或插入。

通常我发现 block 对于导入比委托(delegate)方法更有用:)

关于ios - 处理HTTP Post,然后通过HTTP下载,然后保存到核心数据的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26059030/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com