iOS 15 上 UITableViewController 的便捷初始化崩溃

Posted

技术标签:

【中文标题】iOS 15 上 UITableViewController 的便捷初始化崩溃【英文标题】:Convenience init for UITableViewController crashes on iOS 15 【发布时间】:2021-10-01 09:37:19 【问题描述】:

在新创建的带有故事板的 Xcode 项目中使用 UITableViewController 的便捷初始化在 ios 15 上崩溃,但在 iOS 14 上运行良好。错误消息:

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.

如何重现

打开 Xcode 13 使用 Storyboards 创建一个新项目 选择 iOS 14.0 以获取部署信息 创建一个空的 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)
  

将以下内容添加到主 ViewController
class ViewController: UIViewController 

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


在 iOS 15.0 模拟器上运行项目。 应用崩溃:
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) 

代码在 iOS 14.3 模拟器上运行良好。

【问题讨论】:

便利单元应该调用父级指定的init(self.init)。在这里你间接调用 super.init 。可能是问题的根源吗?即使它似乎适用于旧系统。 便利初始化不能调用父初始化。 “规则 2:便利构造器必须从同一个类中调用另一个构造器。”摘自:Apple Inc. “Swift 编程语言 (Swift 5.5)。”苹果图书。 books.apple.com/at/book/… 你似乎是对的。但是请检查此post 好的,所以也许解决方案是不要继承 UITableViewController,如果你这样做了,不要使用便捷初始化器。 【参考方案1】:

虽然这可能是 UIKit 中的一个错误,但我找到了三个解决方案来解决这个问题。

    不要继承 UITableViewController,见https://***.com/a/30719434/1702958 不要使用便捷初始化器,请参阅https://***.com/a/69121381/1702958 在指定的初始化器前加上@objc,以便 UIKit 找到您指定的 init 方法:
@objc init(data: String) 
    super.init(style: .plain)
    self.data = data

【讨论】:

好点你至少有解决方案。 我最喜欢的解决方案是“根本不要使用 UITableViewController”:D 我讨厌那些东西!遗憾的是,我继承了这段代码,并且它已经在 Objective C 中,所以我很难理解为什么我偶尔会遇到这个崩溃。

以上是关于iOS 15 上 UITableViewController 的便捷初始化崩溃的主要内容,如果未能解决你的问题,请参考以下文章

ios上周期小于15分钟的后台作业

iOS 15 上 UITableViewController 的便捷初始化崩溃

Xcode 12.4 在 Ios 15 上是不是有解决方法?

iOS 应用在适用于 iOS 14 及更低版本但不是 iOS 15+ 的 Testflight 上启动时崩溃

UIGraphicsImageRenderer 在 iOS 15 上生成一个奇怪的顶部填充,在 iOS 14.x 上工作正常

transform:翻译动画在 iOS 15.1 设备上不起作用