【发布时间】:2020-02-06 23:42:58
【问题描述】:
我们的应用因致命异常而崩溃:
Fatal Exception: NSInternalInconsistencyException
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
我们的应用程序过去不会在以前版本的 iOS(12 及更低版本)上以及我在 Xcode 10 上编译时抛出此异常。现在,在 iOS 13.3.1 上并在 Xcode 11.3.1 上编译时,我们的应用程序在 10 秒后崩溃每次都开。我调查了这个异常,似乎苹果已经决定阻止应用程序访问后台线程上的UIKit(如果我在这里错了,请纠正我)。启用 主线程检查器 后,我能够查明导致此崩溃的行。回溯代码让我看到了这一行:
dispatch_async(dispatch_get_main_queue(), ^{
//Code that uses the StoreKit to retrieve purchase data,
//then updates the UI using UIKit based on this information
});
这段代码很好,对吧?因为即使它正在分派这段代码,它也是在主线程中执行的,所以这不应该是问题,对吗?好吧,即使将这段代码移出dispatch_async() 函数后,它仍然会崩溃。然后我查看了这个类的单例,它看起来像这样:
+(instancetype)sharedPurchaseManager
{
static PurchaseManager * sharedPurchaseManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPurchaseManager = [[PurchaseManager alloc] _init];
});
return sharedPurchaseManager;
}
我想知道PurchaseManager 的_init() 是否发生在后台线程中。所以我尝试将PurchaseManager 的分配移出dispatch_once() 块并且应用程序停止崩溃。此外,主线程检查器 停止在使用UIKit 的行中断程序。我很确定将我的_init() 代码移出dispatch_once() 块不是解决我的问题的正确方法,因为这是标准的单例设计模式(如果我错了,请纠正我)。那么我应该如何解决这个问题呢?此外,我们的代码中有大约 10 多次崩溃是由于相同的异常,并且与我们的PurchaseManager 具有相似的设计模式,因此我们需要针对所有这些异常的解决方案。
【问题讨论】:
-
你能上传
[[PurchaseManager alloc] _init]函数里面的代码吗?也许在init函数中有一些代码需要主线程 -
是的,
_init函数中肯定有 UI 代码需要主线程。
标签: ios objective-c xcode ios13 xcode11