【问题标题】:GUI freeze during inserting data in coredata after downloading it from internet从 Internet 下载数据后,在 coredata 中插入数据期间 GUI 冻结
【发布时间】:2016-01-10 06:16:08
【问题描述】:

当我从 Internet 下载大数据(使用 url 分页)并将其保存在核心数据中时,我遇到了一个问题。在保存数据期间,我的应用程序 GUI 被冻结。保存数据后,我的应用程序正常工作。我需要您帮助我解决应用程序冻结问题。

我正在使用异步的NSURLConnection 委托方法下载数据。在connectionDidFinishLoading 方法中,我将数据插入到核心数据中。这是connectionDidFinishLoading 方法中的代码。

[Customer insertCustomerWithList:data]; [self.delegate connectPermissionServiceSuccessful:method];

insertCustomerWithList 上,方法应用程序被冻结。 如果我使用dispatch_async GCD 方法,那么应用程序会因给出此错误而开始崩溃。

ERROR*** 集合 NSCFSet: 0x7c2282e0> 在发生突变时 被枚举。

这是带有 GCD 的代码。

dispatch_queue_t coreDataThread = dispatch_queue_create("com.YourApp.YourThreadName", DISPATCH_QUEUE_CONCURRENT);
                dispatch_async(coreDataThread, ^{
                    [Customer insertCustomerWithList:data];
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.delegate connectPermissionServiceSuccessful:kMethod];
                    });
                });

这是在核心数据中插入数据的insertCustomerWithList 方法。

+ (BOOL) insertCustomerWithList:(NSArray*)customerList

`{NSError *error = nil;
BOOL success = YES;
Customer *obj = nil;
NSManagedObjectContext *managedObjectContext = [NSManagedObjectContext managedObjectContext];`

if (managedObjectContext == nil)
{
    success = NO;
}
@try
{
    for (NSInteger index = 0; index < customerList.count ; index ++)
    {
        NSDictionary* customerInfo = customerList[index];
        obj = [self getCustomerByID:customerInfo[@"_id"]];
        if (obj == nil)
        {
            obj = [NSEntityDescription insertNewObjectForEntityForName:kEntityName
                                                inManagedObjectContext:managedObjectContext];
            [obj updateCustomer:customerInfo];
        }
        else
        {
            [obj updateCustomer:customerInfo];
        }
    }
}
@catch (NSException *exception)
{
    NSLog(@"__ERROR__%@__", exception.reason);
}
[managedObjectContext save:&error];

return success;
`}`

请帮助我解决此问题。

【问题讨论】:

  • 题外话:你不应该使用异常处理。

标签: ios objective-c cocoa-touch core-data


【解决方案1】:

您应该使用NSManagedObjectContextperformBlock API,而不是创建自己的线程。

以下设置不会阻止您的用户界面:

Root context (background) - save to persistent store
Main context (foreground) - child of Root, used on UI
Worker context (background) - child of Main, do heavy loading

您的网络调用的结果块应该创建一个工作上下文并插入新数据。然后save() 方法会将更改“推送”到主上下文,因此如果您的 UI 需要显示新数据,这已经是可能的了。主上下文的save() 将更改推送到根上下文,只有当您在根上下文上调用save() 时,更改才会写入数据库。

使用块 API 进行后台操作,你会没事的。

【讨论】:

    【解决方案2】:

    很难给出一个具体的答案,因为你没有展示你的核心数据堆栈是如何安排的。

    对于基本应用程序,最简单的方法是创建连接到持久存储的持久后台上下文 (NSPrivateQueueConcurrencyType)。对于主线程,使用NSMainQueueConcurrencyType 创建背景上下文的子线程。

    您通过向其发出performBlock 消息来编写背景上下文。您可以通过设置 NSFetchedResultsController 在子上下文中收到通知。

    【讨论】:

      猜你喜欢
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多