我有下一个问题:我有大约7000个实体的数据库,当我需要更新它们时(我有解析的XML文件)首先我删除所有实体,之后我解析XML文件,之后我创建了新的实体和保存上下文。之前所有工作都很完美:没有冻结,没有崩溃 - 在iOS 7上都很快。
但是在发布iOS 8时出现了问题:
我通过为所有操作提供一个上下文来解决这个问题:删除,创建和保存。
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中的进度。
我没有其他可以操作核心数据对象的线程。
有app的工作链接:http://rghost.ru/60274051 6秒后:出于测试目的,我启动NSTimer,每隔0.3秒使用假数据更新进度,以便在开始删除和保存操作之前填充50%的进度(更新进度在主队列中)。定时器触发几次然后保存进程在后台线程中启动但阻塞主线程(据我所知)并将设置进度操作移动到结束(如果我理解正确)。 1:08:然后在保存结束后我开始解析xml文件。这是删除后保存上下文的线程。您可以看到进度更新。在这个视频中,由于很多操作,它可以处理bug,但是你可以相信我的工作和看起来很好。解析7000个对象后,我保存上下文AGAIN并保存操作不会阻止UI线程。
其他信息: 关系:
答案 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
}];
}];