在后台保存条目会导致崩溃并仍然阻塞 UI

Posted

技术标签:

【中文标题】在后台保存条目会导致崩溃并仍然阻塞 UI【英文标题】:Saving entries in background cause crash and still blocking the UI 【发布时间】:2013-06-10 11:04:01 【问题描述】:

我从远程 API 获得响应,对其进行解析并分配到一个数组中,然后循环该数组以保存实体中的每个元素:

        for (id element in arrayProduct) 

            [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) 

                Product *product = [Product MR_createInContext:localContext];

                ([element valueForKey:@"Category Id"] == [NSNull null])?(product.category_id = [NSNumber numberWithInt:-1]):(product.category_id = [NSNumber numberWithInt:[[element valueForKey:@"Category Id"] intValue]]);

 ];


for 循环代码正在保存到 coredata 中,但一段时间后,应用程序崩溃,其余条目被中断,因此没有保存。

这是 for 循环执行保存时的日志:

2013-06-10 11:54:15:461 App[2718:2311] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:] [Line 42] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x1fd88c70) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING
2013-06-10 11:54:15:471 App[2718:2311] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:] [Line 42] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x1fd88c70) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING
2013-06-10 11:54:16:099 App[2718:135939] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:] [Line 54] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x20d96320) → Saving <NSManagedObjectContext (0x20d96320): *** UNNAMED ***> on *** BACKGROUND THREAD *
2013-06-10 11:54:16:101 App[2718:96515] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:] [Line 54] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x20d966e0) → Saving <NSManagedObjectContext (0x20d966e0): *** UNNAMED ***> on *** BACKGROUND THREAD *

我正在使用saveWithBlock: 方法,因为不推荐使用像saveInBackgroundWithBlock: 这样的其他方法。

我有几个问题:

-我应该在块内进行 for 循环,还是应该将块放在 for 循环内? -我应该使用什么方法来确保应用程序不会崩溃?是在后台保存数据的方法吗?因为保存时 UI 仍然被阻止。

【问题讨论】:

为什么不把循环放在块里面...?另外,你能发布崩溃日志吗? 【参考方案1】:

试着改成这个……

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) 
    for (id element in arrayProduct) 
        Product *product = [Product MR_createInContext:localContext];

        // ([element valueForKey:@"Category Id"] == [NSNull null]) ? (product.category_id = [NSNumber numberWithInt:-1]):(product.category_id = [NSNumber numberWithInt:[[element valueForKey:@"Category Id"] intValue]]);

        // that line of code is really hard to read. Changed it to this...

        product.category_id = element[@"Category Id"] == [NSNull null] ? @-1 : element[@"Category Id"];
    
];

我想它试图创建和保存太多可能导致崩溃的上下文?

另外,你遇到了什么崩溃?

【讨论】:

是的,正如我在问题中提到的,在发布我的问题之前,我应该尝试将 for 循环放在块内。 啊,抱歉,没看到,抱歉。您还会发现(我也遇到过)与前台上下文的合并会阻塞 UI。使用您当前的方法,您可能有数百个合并,但使用此方法您将只有一个。 顺便说一句,我应该[localContext MR_save]; 来验证保存吗?因为我在一些博客中看到了这一点。 不,该块将为您完成所有保存。无需显式调用 save。

以上是关于在后台保存条目会导致崩溃并仍然阻塞 UI的主要内容,如果未能解决你的问题,请参考以下文章

后台位置的核心数据更新位置导致阻塞 UI

异步任务阻塞 UI 线程

Async/Await 仍然阻塞 UI?

Redis 阻塞保存

写入 coredata,即使在后台线程上完成,也会严重阻塞 UI

redis的incr和decr高并发会形成线程阻塞吗