在两个嵌套子类中调用 super.viewDidLoad() 时,我遇到了 Swift 的无限循环

Posted

技术标签:

【中文标题】在两个嵌套子类中调用 super.viewDidLoad() 时,我遇到了 Swift 的无限循环【英文标题】:I'm getting an infinite loop with Swift when calling super.viewDidLoad() in two nested subclasses 【发布时间】:2015-01-12 09:18:22 【问题描述】:

我正在开发一个用 Swift 编写的 ios 应用程序。我有一个 UITabBarController 的子类,然后是一个嵌套的子类:

class HWTabBarController: UITabBarController 
    override func viewDidLoad() 
        super.viewDidLoad()
        ...
    


class MainTabBarController: HWTabBarController 
    override func viewDidLoad() 
        super.viewDidLoad()
        ...
    

这在 iOS 模拟器中运行良好,甚至在我在 iPhone 上调试应用程序时也是如此。 但是当我将应用程序存档并使用 TestFlight 将其发送到我的手机时,它会崩溃。

我的崩溃日志充满了这个无限循环:

22  HDWR                           0x00145e10 @objc HDWR.MainTabBarController.viewDidLoad (HDWR.MainTabBarController)() -> () (MainTabBarController.swift:16)
23  HDWR                           0x00262867 NRMA__voidParamHandler
24  HDWR                           0x0014ea00 HDWR.HWTabBarController.viewDidLoad (HDWR.HWTabBarController)() -> () (HWTabBarController.swift:24)
25  HDWR                           0x00145e10 @objc HDWR.MainTabBarController.viewDidLoad (HDWR.MainTabBarController)() -> () (MainTabBarController.swift:16)
26  HDWR                           0x00262867 NRMA__voidParamHandler
27  HDWR                           0x0014ea00 HDWR.HWTabBarController.viewDidLoad (HDWR.HWTabBarController)() -> () (HWTabBarController.swift:24)
28  HDWR                           0x00145e10 @objc HDWR.MainTabBarController.viewDidLoad (HDWR.MainTabBarController)() -> () (MainTabBarController.swift:16)
29  HDWR                           0x00262867 NRMA__voidParamHandler
30  HDWR                           0x0014ea00 HDWR.HWTabBarController.viewDidLoad (HDWR.HWTabBarController)() -> () (HWTabBarController.swift:24)
31  HDWR                           0x00145e10 @objc HDWR.MainTabBarController.viewDidLoad (HDWR.MainTabBarController)() -> () (MainTabBarController.swift:16)
32  HDWR                           0x00262867 NRMA__voidParamHandler
33  HDWR                           0x0014ea00 HDWR.HWTabBarController.viewDidLoad (HDWR.HWTabBarController)() -> () (HWTabBarController.swift:24)

voidParamHandler 指令是什么,为什么它会返回到MainTabBarController.viewDidLoad

我在这里做错了吗?或者这是 Swift 中的一个错误?

【问题讨论】:

类是如何实例化的? 正常情况下:let mainController = MainTabBarController(). 您是否尝试删除应用程序并清理 Xcode 上的构建并重新安装?有时这可以解决随机问题。 是的,已经尝试过了。我实际上正在重新讨论这个问题,因为无限循环出现在不同的地方,那里还有 2 个级别的子类化并调用 super.viewDidLoad() 我尝试使用测试应用程序重现此内容,但无法使其崩溃!不过,这里是 repo:github.com/ndbroadbent/SwiftSuperCrash 如果我能让它在我的手机上崩溃,我会更新。 【参考方案1】:

您是否在您的应用中使用New Relic? (我从所有这些NRMA__voidParamHandler 引用中猜测你是。)我遇到了这个确切的问题。我禁用了 New Relic SDK 并且从 Testflight 下载的构建停止崩溃。我还没有报告错误,但你/我/我们可能应该报告。

【讨论】:

就是这样!我应该意识到 NRMA 与 New Relic 有关。我已经更新了我的 POC 存储库,它现在重现了这个崩溃:github.com/ndbroadbent/SwiftSuperCrash 非常感谢!! 我在 New Relic 论坛上报告了一个错误:discuss.newrelic.com/t/… 对于正在阅读本文的任何人,请查看 Bryce Buchanan 的答案,将 dynamic 添加到 New Relic 仪器解决此问题的方法中。【参考方案2】:

添加了 swift 后,objective-c 所拥有的所有甜蜜的动态函数查找功能都被取消了。要恢复该功能,您需要将“动态”声明标志添加到 New Relic 仪器的所有方法中。

像这样:

class HWTabBarController: UITabBarController 
    override dynamic func viewDidLoad() 
        super.viewDidLoad()
        ...
    


class MainTabBarController: HWTabBarController 
    override dynamic func viewDidLoad() 
        super.viewDidLoad()
        ...
    

更多详细信息,包括其中包含哪些功能,请点击此处:https://docs.newrelic.com/docs/mobile-monitoring/new-relic-mobile/getting-started/enabling-swift-interaction-traces

【讨论】:

这可以连接到任何 Obj-C swizzles 吗?【参考方案3】:

我刚刚下载了 repo,在我自己的个人资料上签名,一切似乎都按照你的程序运行。没有无限循环,没有崩溃。这也是通过试飞。这使我相信您的系统某处存在一些错误。我建议做一些事情...

    清理构建 cmd+alt+shift+k && 删除手机上的应用程序。 关闭 Xcode,然后删除您的派生数据。 (如果您还没有完成此操作,我会详细说明如何操作。) 如果可行,将其注册为试飞中的新应用程序。

我的想法是,当您删除派生数据时它会有所帮助,但我会这样做只是为了让您知道一切都是干净的。同样,我在任何阶段都没有遇到这个问题:模拟器,直接从 Xcode 安装或通过 Test Flight 下载。

还要确保捆绑包 ID 已正确注册,并且在 Test Flight 的服务器端一切正常。我无法想象为什么它会导致循环,但这是一种奇怪的情况,所以让我们看看会发生什么。 :^)

【讨论】:

对不起,我在上面试图提到我也无法让测试应用程序崩溃,所以它只发生在我们的真实应用程序上。我将继续尝试将更多代码添加到示例应用程序中,看看我是否可以重现它。感谢您对此进行调查! @nathan.f77 你能发布你在程序中有任何forwhile 循环的代码吗? viewDidLoad 只能调用一次。 嗨,斯科特,再次感谢您的宝贵时间!另一位用户帮助我弄清楚这是由 New Relic Agent 试图分析我的代码引起的:***.com/a/27416135/304706 @nathan.f77 不用担心,很高兴你明白了!

以上是关于在两个嵌套子类中调用 super.viewDidLoad() 时,我遇到了 Swift 的无限循环的主要内容,如果未能解决你的问题,请参考以下文章

Python - 追加到嵌套在 dict 子类中的列表

Python v2嵌套子类“全局名称” ' 没有定义”

C#中子类构造函数中如何调用父类构造函数

wpf窗口嵌套

数组不存储值

尝试创建一个父类,在父类中创建两个方法,在子类中覆盖第二个方法,为子类创建一个对象,将它向上转型到基类并调用这个方法。