Наше приложение падает с фатальным исключением:
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 секунд после каждого открытия. Я рассмотрел это исключение, и кажется, что Apple решила запретить приложениям получать доступ к UIKit
в фоновых потоках (пожалуйста, исправьте меня, если я здесь не прав). После включения Main Thread Checker я смог точно определить линию, которая вызвала этот крей sh. Возврат кода привел меня к этой строке:
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;
}
И я подумал, что _init()
для PurchaseManager
происходит в фоновом потоке. Поэтому я попытался переместить выделение для PurchaseManager
из блока dispatch_once()
, и приложение перестало падать. Кроме того, Main Thread Checker прекратил прерывать программу в строке, которая использует UIKit
. Я почти уверен, что перемещение моего _init()
кода из блока dispatch_once()
не является правильным способом решения проблемы go, так как это стандартный шаблон проектирования Singleton (пожалуйста, исправьте меня, если я ошибаюсь ). Итак, как мне go решить проблему? Кроме того, в нашем коде более 10 сбоев, вызванных тем же исключением, и с шаблоном проектирования, аналогичным нашему PurchaseManager
, поэтому мы хотели бы найти решение для всех этих исключений.