Xcode 13 beta 5 错误:UIViewController 缺少初始化期间填充的初始特征集合

Posted

技术标签:

【中文标题】Xcode 13 beta 5 错误:UIViewController 缺少初始化期间填充的初始特征集合【英文标题】:Xcode 13 beta 5 error: UIViewController is missing its initial trait collection populated during initialization 【发布时间】:2021-11-04 14:37:43 【问题描述】:

在 Xcode 13 beta 5 构建之前,应用程序运行良好。

在我们的视图控制器的这行初始化代码中突然出现这个错误:

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

此代码在 Xcode 12 中运行良好,并且没有任何更改,现在中断:

'NSInternalInconsistencyException',原因:'UIViewController 是 缺少初始化期间填充的初始特征集合。 这是一个严重的错误,可能是由访问属性或 调用 UIViewController 之前视图控制器上的方法 初始化器。视图控制器:'

我在谷歌上搜索了一下,只知道found 1 obscure thread 解决了这个问题,但帮助不大。

有时设置断点并介入可以让它在不崩溃的情况下工作,因此引擎盖下似乎存在某种布局竞争条件,但我正在努力调试。我试过睡觉,但没用。

感谢任何有关如何调试此问题的建议。现在我无法获得额外的信息来调试。如果您知道可能导致此问题的原因或在哪里查看,我将不胜感激您的意见。

这是错误堆栈跟踪:

*** 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
)

【问题讨论】:

【参考方案1】:

简短描述:对于基于objective-C的实现,可以将对象方法转换为类方法。

xcode13GM Seed 上报告了以下错误。错误日志:

*** 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: <MyViewController: 0x7fa5ae2356c0>'

对于以下init method

- (instancetype)initWithModel:(MyModel *)myModel 
    
    MyViewController *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"MyViewController"];
    vc.model = myModel;
    return vc;

init 以下列方式从另一个 View Controller 调用。

// Before - invoking object method -- Results in the error
MyViewController *viewController = [[MyViewController alloc] initWithModel:testModel];

// After - invoking Class method
MyViewController *viewController = [MyViewController initWithModel:testModel];

为了解决它,我将init方法转换为类方法。

+ (instancetype)initWithModel:(MyModel *)myModel 
    
    MyViewController *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"MyViewController"];
    vc.model = myModel;
    return vc;

【讨论】:

【参考方案2】:

注释掉很多代码后,又开始报新的错误:

致命错误:对“PaymentPickerViewController”类使用未实现的初始化程序“init(style:)”

进一步研究行为,似乎我们有一个 objc 初始化扩展。我相信在这个 Xcode 13 中,objc 代码会被破坏并且不会“看到”对初始化程序的根调用。

我们原来的初始化代码路径是这样的:

@objc extension PaymentPickerViewController 
    convenience init() 
        dataProvider = DataProvider()
        self.init(dataProvider: dataProvider)
    


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

修复明确地覆盖了我们想从 super 使用的 swift init:

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

这会强制 objc 看到正确的初始化,然后它就可以工作了。

我担心我发布的原始错误非常具有误导性,因此希望这可以帮助遇到此问题的任何人。

【讨论】:

我不得不恭敬地不同意。原始错误源于目标 c 无法看到初始化程序,而这仅在 xcode 13 中开始发生。如果您检查谷歌,几乎没有关于此错误的信息。错误本身具有误导性,真正的来源似乎是 objc 代码无法看到 swift 初始化程序。如果有更明确的建议,您可以建议我开放,但我相信这个答案是解决办法。 我在评估该参数时遇到了一些麻烦,因为您的代码无法编译。那是你的真实代码吗?例如你说self.init(dp:),但你没有init(dp:);你有一个不同的初始化器,init(dataProvider:)。我不明白这一切是如何联系在一起的。似乎缺少一些拼图。 我更新了初始化。这是代码的模拟表示。问题的根源是:init 方法是 swift 类中的一个 objc 扩展,在运行时没有被 objc 代码看到。通过显式覆盖我们需要使用的 tableview init,它解决了这个问题。 在我进一步深入研究之前,我的回答是否相关? ***.com/a/30719434/341994 我不相信,不。

以上是关于Xcode 13 beta 5 错误:UIViewController 缺少初始化期间填充的初始特征集合的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 6 beta 7 UIView.animateWithDuration 调用中的额外参数“usingSpringWithDamping”

Swift 2/Xcode 7 beta - 多个位掩码产生错误

无法开发应用程序,因为在 iOS 13.0/Xcode 11 beta 5 中“无法在设备上找到应用程序”[重复]

更新到 Xcode 7 Beta 5 并收到此错误:失败,退出代码 6

Xcode 11 beta -playbackState 仅在 iOS 13.0 或更新版本中可用

Xcode 11 beta 中的配置文件错误