0

Using a convenience init for a UITableViewController in a freshly created Xcode project with storyboards crashes on iOS 15, but works fine on iOS 14. The error message:

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.

How to reproduce

  • Open Xcode 13
  • Create a new project with Storyboards
  • Select iOS 14.0 for deployment info
  • Create an empty UITableViewController
class CustomTableViewController : UITableViewController {
 
  var data:String?
   
  convenience init() {
    self.init(data: "test")
  }
   
  init(data: String) {
    self.data = data
    super.init(style: .plain)
  }
     
  required init?(coder: NSCoder) {
    super.init(coder: coder)
  }
}
  • Add the following to the main ViewController
class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
     
    _ = CustomTableViewController()
  }

}
  • Run the project on an iOS 15.0 simulator.
  • The app crashes with:
2021-10-01 10:38:40.146584+0200 CustomViewControllerInit[62559:627294] *** Assertion failure in UITraitCollection *UIViewControllerMissingInitialTraitCollection(UIViewController *__strong)(), UIViewController.m:2434
2021-10-01 10:38:40.155555+0200 CustomViewControllerInit[62559:627294] *** Terminating app due to uncaught exception '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: 0x7fe1a7407580>'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff203fbbb4 __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff2019ebe7 objc_exception_throw + 48
    2   Foundation                          0x00007fff20750da9 -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
    3   UIKitCore                           0x00007fff2483b6c6 UIViewControllerMissingInitialTraitCollection + 188
    4   UIKitCore                           0x00007fff2483fbef -[UIViewController traitCollection] + 155
    5   UIKitCore                           0x00007fff2482e93a -[UITableViewController dealloc] + 196
    6   CustomViewControllerInit            0x000000010d33ea3d $s24CustomViewControllerInit0a5TablebC0CACycfc + 157
    7   CustomViewControllerInit            0x000000010d33ea6f $s24CustomViewControllerInit0a5TablebC0CACycfcTo + 15
    8   CustomViewControllerInit            0x000000010d33e99b $s24CustomViewControllerInit0a5TablebC0CACycfC + 27
    9   CustomViewControllerInit            0x000000010d33d50d $s24CustomViewControllerInit0bC0C11viewDidLoadyyF + 109
    10  CustomViewControllerInit            0x000000010d33d55c $s24CustomViewControllerInit0bC0C11viewDidLoadyyFTo + 28
    11  UIKitCore                           0x00007fff2483d2f0 -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 88
    12  UIKitCore                           0x00007fff24841cf4 -[UIViewController loadViewIfRequired] + 1187
    13  UIKitCore                           0x00007fff248420fc -[UIViewController view] + 27
    14  UIKitCore                           0x00007fff2503eb8b -[UIWindow addRootViewControllerViewIfPossible] + 313
    15  UIKitCore                           0x00007fff2503e279 -[UIWindow _updateLayerOrderingAndSetLayerHidden:actionBlock:] + 222
    16  UIKitCore                           0x00007fff2503f26a -[UIWindow _setHidden:forced:] + 409
    17  UIKit                               0x00007fff5963dc30 -[UIWindowAccessibility _orderFrontWithoutMakingKey] + 126
    18  UIKitCore                           0x00007fff25051e5a -[UIWindow _mainQueue_makeKeyAndVisible] + 47
    19  UIKitCore                           0x00007fff252bd80c -[UIWindowScene _makeKeyAndVisibleIfNeeded] + 202
    20  UIKitCore                           0x00007fff24386def +[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 1605
    21  UIKitCore                           0x00007fff24ffd75c -[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 1253
    22  UIKitCore                           0x00007fff24ffdc0b -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 289
    23  UIKitCore                           0x00007fff24a7e62e -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 358
    24  FrontBoardServices                  0x00007fff26483d98 -[FBSScene _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 419
    25  FrontBoardServices                  0x00007fff264b04a3 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke.180 + 102
    26  FrontBoardServices                  0x00007fff2649221a -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 209
    27  FrontBoardServices                  0x00007fff264b0082 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke + 352
    28  libdispatch.dylib                   0x000000010d4e8c0c _dispatch_client_callout + 8
    29  libdispatch.dylib                   0x000000010d4ebb7f _dispatch_block_invoke_direct + 295
    30  FrontBoardServices                  0x00007fff264d6dc8 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
    31  FrontBoardServices                  0x00007fff264d6cbe -[FBSSerialQueue _targetQueue_performNextIfPossible] + 174
    32  FrontBoardServices                  0x00007fff264d6df0 -[FBSSerialQueue _performNextFromRunLoopSource] + 19
    33  CoreFoundation                      0x00007fff20369e25 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    34  CoreFoundation                      0x00007fff20369d1d __CFRunLoopDoSource0 + 180
    35  CoreFoundation                      0x00007fff20369254 __CFRunLoopDoSources0 + 340
    36  CoreFoundation                      0x00007fff20363951 __CFRunLoopRun + 875
    37  CoreFoundation                      0x00007fff20363103 CFRunLoopRunSpecific + 567
    38  GraphicsServices                    0x00007fff2c851cd3 GSEventRunModal + 139
    39  UIKitCore                           0x00007fff24ffbe63 -[UIApplication _run] + 928
    40  UIKitCore                           0x00007fff25000a53 UIApplicationMain + 101
    41  libswiftUIKit.dylib                 0x00007fff5933d052 $s5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF + 98
    42  CustomViewControllerInit            0x000000010d33e088 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 104
    43  CustomViewControllerInit            0x000000010d33e017 $s24CustomViewControllerInit11AppDelegateC5$mainyyFZ + 39
    44  CustomViewControllerInit            0x000000010d33e108 main + 24
    45  dyld                                0x000000010d365e1e start_sim + 10
    46  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception '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: 0x7fe1a7407580>'
terminating with uncaught exception of type NSException
CoreSimulator 776.3 - Device: iPhone 8 (1CCAF02C-6FB7-4DDB-A6F7-3CE9009A2EB2) - Runtime: iOS 15.0 (19A339) - DeviceType: iPhone 8
(lldb) 

The code works fine on an iOS 14.3 simulator.

Philipp Hofmann
  • 3,388
  • 26
  • 32
  • Convenience unit should call parent designated init (self.init). Here you indirectly call super.init . May be it the source of the problem ? Even if it seems to work on older systems. – Ptit Xav Oct 01 '21 at 10:17
  • A convenience init can't call the parent init. “Rule 2: A convenience initializer must call another initializer from the same class.” Excerpt From: Apple Inc. “The Swift Programming Language (Swift 5.5).” Apple Books. https://books.apple.com/at/book/the-swift-programming-language-swift-5-5/id881256329 – Philipp Hofmann Oct 01 '21 at 10:22
  • You seems right. But check this [post](https://stackoverflow.com/questions/69092599/xcode-13-beta-5-error-uiviewcontroller-is-missing-its-initial-trait-collection) – Ptit Xav Oct 01 '21 at 10:37
  • Okay, so maybe then the solution is don't subclass UITableViewController, and if you do, don't use a convenience initializer. – Philipp Hofmann Oct 01 '21 at 10:56

1 Answers1

1

Although this could be a bug in UIKit, I found three solutions to fix this problem.

  1. Don't subclass UITableViewController, see https://stackoverflow.com/a/30719434/1702958
  2. Don't use a convenience initializer, see https://stackoverflow.com/a/69121381/1702958
  3. Prefix the designated initializer with @objc so UIKit finds your designated init method:
@objc init(data: String) {
    super.init(style: .plain)
    self.data = data
}
Philipp Hofmann
  • 3,388
  • 26
  • 32
  • Good point you have at least solutions. – Ptit Xav Oct 01 '21 at 11:12
  • My favoured solution would be 'Don't use UITableViewController at all' :D I hate those things! Sadly I inherited this code, and it's in Objective C already, so I'm struggling to see why I'm occasionally getting this crash. – Ash Feb 15 '22 at 08:49