出于某种原因,使用dispatch_async和Core Data会导致我的应用程序完全冻结,但不会崩溃。
用户界面没有响应。该应用程序不会崩溃。
该应用使用[[UIAccelermeter sharedAccelerometer] setDelegate: self]
连续获取加速度计值。 “accelerometer:didAccelerate:
”回调在主线程上运行。发生此问题时,不再执行回调。
因此主线程似乎是“冻结”。
我在我的应用中使用NSURLConnection
将HTTP请求发送到我的服务器。在connectionDidFinishLoading中,处理响应数据时,执行大约需要2秒,用户界面在这2秒内没有响应,因为它在主线程中运行。
经过一些研究,似乎gcd/dispatch_async
是在这种情况下在后台执行数据处理的最佳解决方案。所以,在connectionDidFinishLoading
中,我添加了以下gcd调用:
dispatch_queue_t queue;
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[self handleTheData: connection];
});
这有时会很好,但它会导致应用程序随机冻结 - 即使使用相同的代码,核心数据存储中的数据相同,重复测试表明可以在X%的时间内观察到症状。发生问题的可能性受到一些因素的影响,下面将进一步解释。
它检查NSURLConnection
的响应数据,这是JSON格式的字符串。该字符串是3个实体列表,每个实体是一个数组数组。因此,有一些代码可以将JSON格式的字符串转换为自定义对象的3个NSMutableArray,其中每个对象都是一个子类NSManagedObject。
在转换期间,由于这些对象是“临时的”,因为它们可能会或可能不会永久存储,所以它们是在“nil”NSManagedObjectContext中创建的,如下所示:
SampleEntity *newEntity=
(SampleEntity *) [[NSManagedObject alloc] initWithEntity:entity
insertIntoManagedObjectContext:nil
];
这样,它们就不会与主要背景混合在一起。
然后将这些新对象与数据存储中的现有实体进行比较。因此,有一些代码重复从数据存储中获取以查看是否已存在特定的新实体,并且根据新实体的数据,新实体可以保存到数据存储,或者可以更新现有实体。 / p>
经常调用[managedObjectContext save:& error]以确保永久保存更改。
如症状部分所述,使用[[UIAccelermeter sharedAccelerometer] setDelegate:self]
在主线程的后台运行AccelerometerAudioUnits也已设置为在后台运行(根据Apple文档在单独的“优先级”线程上)以产生声音。
发现发生问题的可能性受以下因素影响:
此外,即使主线程未冻结,也会发生另一个问题。数据处理代码将中途结束而不会抛出错误。
有趣的问题不是吗? :)
修改的
答案 0 :(得分:2)
我最终提供了Apple开发支持的技术支持事件。我也为他们提供了一个样本项目,它显示了相同的症状。
几天之后,我得到了他们的回复,它向我指出了CoreData编程指南,并指出了由调度队列运行的代码需要拥有自己的私有NSManagedObjectContext。
https://developer.apple.com/documentation/coredata/using_core_data_in_the_background
一旦我遵循了建议,问题似乎已经解决了!