MagicalRecord:删除后保存上下文太长

时间:2015-01-10 22:58:45

标签: ios objective-c multithreading magicalrecord

我有下一个问题:我有大约7000个实体的数据库,当我需要更新它们时(我有解析的XML文件)首先我删除所有实体,之后我解析XML文件,之后我创建了新的实体和保存上下文。之前所有工作都很完美:没有冻结,没有崩溃 - 在iOS 7上都很快。

但是在发布iOS 8时出现了问题: enter image description here

我通过为所有操作提供一个上下文来解决这个问题:删除,创建和保存。

BUT!我得到了什么:

当我在我的设备上安装app时一切顺利:没有删除,只有创建实体,7000个术语和7个组被解析得如此之快(在iPhone 6上大约4秒),节省也很快。

当我在plist文件中更改数据库版本(增加)时,我的解析器启动了这个算法:


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
            [Term MR_truncateAllInContext:localContext];
            [Group MR_truncateAllInContext:localContext];
        } completion:^(BOOL success, NSError *error) {
            [self parseTermsInContext:[NSManagedObjectContext contextForCurrentThread] from:self.count];
        }];
    });

" saveWithBlock"方法块线程1(在分析器中),我的CPU加载到99-108(显然是错误)百分比(每次下一次更新保存操作需要越来越多的秒,从20秒甚至更多,超过120秒)。

我已经尝试过这种方式(我用一种方法为你收集了所有操作):

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread];
        NSMutableArray *objects = [NSMutableArray arrayWithArray:[Group MR_findAllInContext:localContext]];
        [objects addObjectsFromArray:[Term MR_findAllInContext:localContext]];

        if (objects && [objects count] > 0) {
            for (NSManagedObject *object in objects) {
                [object MR_deleteInContext:localContext];
            }
            [localContext MR_saveToPersistentStoreAndWait];
        }
        [self parseTermsInContext:localContext from:self.count];
    });

此处操作" MR_saveToPersistentStoreAndWait"需要很长时间,比如" saveWithBlock"。

我在删除后没有保存上下文就试过了,就是行" [localContext MR_saveToPersistentStoreAndWait];"不存在。通过这种方式,组和术语也被删除得如此之快,以后它们也被解析得如此之快,但保存上下文的时间太长了。

我不知道为什么,但即使我开始删除并保存后台线程保存操作中的进程冻结UI线程(在UI线程中我显示从0到100的进度)。当我在这个线程中解析XML时,我发送消息来查看一个术语被解析并设置百分比进度,委托调用方法在主队列中设置ProgressView中的进度。

enter image description here

我没有其他可以操作核心数据对象的线程。

有app的工作链接:http://rghost.ru/60274051 6秒后:出于测试目的,我启动NSTimer,每隔0.3秒使用假数据更新进度,以便在开始删除和保存操作之前填充50%的进度(更新进度在主队列中)。定时器触发几次然后保存进程在后台线程中启动但阻塞主线程(据我所知)并将设置进度操作移动到结束(如果我理解正确)。 1:08:然后在保存结束后我开始解析xml文件。这是删除后保存上下文的线程。您可以看到进度更新。在这个视频中,由于很多操作,它可以处理bug,但是你可以相信我的工作和看起来很好。解析7000个对象后,我保存上下文AGAIN并保存操作不会阻止UI线程。

其他信息: 关系: enter image description here

1 个答案:

答案 0 :(得分:0)

    } completion:^(BOOL success, NSError *error) {
        [self parseTermsInContext:[NSManagedObjectContext contextForCurrentThread] from:self.count];
    }];

阻止上面的主线程调用(块UI),所以contextForCurrentThread == UI Thread

而不是迭代删除所有对象,你可以使用TruncateAll

我的建议是:

// saveWithBlock - already perform block in background thread
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    [Term MR_truncateAllInContext:localContext];
    [Group MR_truncateAllInContext:localContext];
} completion:^(BOOL success, NSError *error) {
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        // self must be weak!
        [self parseTermsInContext:localContext from:self.count];
    } completion:^(BOOL success, NSError *error) {
        // Update UI
    }];
}];