Search code examples
swiftxcodeuitraitcollectionxcode13

Xcode 13 beta 5 error: UIViewController is missing its initial trait collection populated during initialization


App was working fine until Xcode 13 beta 5 builds.

Suddenly get this error in this init line of code in our view controller:

init(dataProvider: DataProvider) {
    self.dataProvider = dataProvider
    super.init(style: .plain)
    dataProvider.delegate = self
}

This code was working fine in Xcode 12 and with no changes it now breaks with:

'NSInternalInconsistencyException', reason: 'UIViewController is missing its initial trait collection populated during initialization. This is a serious bug, likely caused by accessing properties or methods on the view controller before calling a UIViewController initializer. View controller: <UITableViewController: 0x7f7fbd291bb0>'

I googled around and only found 1 obscure thread on the issue but it wasnt much help.

Sometimes putting a breakpoint and stepping in allows it to work without crashing so there seems to be some sort of layout race condition under the hood but I am struggling to debug. I tried putting a sleep in but that doesn't work.

Any and all advice on how to debug this is appreciated. Right now I am unable to get additional info in order to debug. If you know what might be causing this or where to look I would appreciate your input.

Here is the error stack trace:

*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff203fc8a8 __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff2019ebe7 objc_exception_throw + 48
    2   Foundation                          0x00007fff207501c9 -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
    3   UIKitCore                           0x00007fff248310ed UIViewControllerMissingInitialTraitCollection + 188
    4   UIKitCore                           0x00007fff24835616 -[UIViewController traitCollection] + 155
    5   UIKitCore                           0x00007fff24824392 -[UITableViewController dealloc] + 196
    6   App Dev                             0x000000010e4f5680 $s05AppLaB027MyViewController
    C14paymentMethods13selectedIndex5offer8delegateACSaySo16AppPaymentMethodCG_SiAA5Offer_pAA08CheckoutcD8Delegate_pSgtcfc + 368
    7   App Dev                             0x000000010e4f5726 $s05AppLaB027MyViewController
    C14paymentMethods13selectedIndex5offer8delegateACSaySo16AppPaymentMethodCG_SiAA5Offer_pAA08CheckoutcD8Delegate_pSgtcfcTo + 102
    8   App Dev                             0x000000010e289291 -[CartViewController showPaymentMethodPickerWithPaymentMethods:] + 385
    9   App Dev                             0x000000010e289055 __59-[CartViewController showPaymentMethodPickerOrEntryForm]_block_invoke + 245
    10  App Dev                             0x000000010e7075ae $sSo16AppServiceResultVSo7NSArrayCSgSo7NSErrorCSgIeyByyy_ABSaySo16AppPaymentMethodCGSgs5Error_pSgIegygg_TR + 222
    11  App Dev                             0x000000010e707246 $sSo17AppAccountServiceC05AppLaD0E19fetchPaymentMethods11forListType7refresh09preferredF6Method10completionSo17AppRequestReceipt_pSgAC0fmiJ0O_S2bySo16AppServiceResultV_SaySo010AppPaymentM0CGSgs5Error_pSgtcSgtFyAN_ArTtcfU_ + 630
    12  App Dev                             0x000000010e707333 $sSo17AppAccountServiceC05AppLaD0E19fetchPaymentMethods11forListType7refresh09preferredF6Method10completionSo17AppRequestReceipt_pSgAC0fmiJ0O_S2bySo16AppServiceResultV_SaySo010AppPaymentM0CGSgs5Error_pSgtcSgtFyAN_ArTtcfU_TA + 35
    13  App Dev                             0x000000010e580474 $sSo16AppServiceResultVSaySo16AppPaymentMethodCGSgs5Error_pSgIegygg_ABSo7NSArrayCSgSo7NSErrorCSgIeyByyy_TR + 212
    14  App Dev                             0x000000010e39bcad __79-[AppAccountV3DAO fetchPaymentMethodsRefresh:preferredPaymentMethod:withBlock:]_block_invoke + 45
    15  libdispatch.dylib                   0x0000000110c18a18 _dispatch_call_block_and_release + 12
    16  libdispatch.dylib                   0x0000000110c19bfc _dispatch_client_callout + 8
    17  libdispatch.dylib                   0x0000000110c28366 _dispatch_main_queue_callback_4CF + 1195
    18  CoreFoundation                      0x00007fff2036a555 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    19  CoreFoundation                      0x00007fff20364db2 __CFRunLoopRun + 2772
    20  CoreFoundation                      0x00007fff20363dfb CFRunLoopRunSpecific + 567
    21  GraphicsServices                    0x00007fff2cbb5cd3 GSEventRunModal + 139
    22  UIKitCore                           0x00007fff24fee193 -[UIApplication _run] + 928
    23  UIKitCore                           0x00007fff24ff2bfb UIApplicationMain + 101
    24  App Dev                             0x000000010e267120 main + 96
    25  dyld                                0x0000000110654e1e start_sim + 10
    26  ???                                 0x0000000000000001 0x0 + 1
    27  ???                                 0x0000000000000001 0x0 + 1
)

Solution

  • After commenting out a lot of code, I started getting a new error:

    fatal error: Use of unimplemented initializer ‘init(style:)’ for class ‘PaymentPickerViewController’

    Looking into the behaviour some more, it seems we have an objc initialized extension. I believe in this Xcode 13, the objc code gets mangled and doesn't "see" the root call to the initializer.

    Our original init code path was this:

    @objc extension PaymentPickerViewController {
        convenience init() {
            dataProvider = DataProvider()
            self.init(dataProvider: dataProvider)
        }
    }
    
    init(dataProvider: DataProvider) {
       self.dataProvider = dataProvider
       super.init(style: .plain)        
    }
    

    The fix was explicitly overriding the swift init we wanted to use from the super:

    override init(style: UITableView.Style) {
        super.init(style: .plain)
         self.dataProvider = DataProvider()
    }
    

    This forces the objc to see the correct init and then it works.

    I fear the original error that I posted is very misleading so hopefully this helps anyone who runs into this issue.