【问题标题】:UISwitch not deallocatingUISwitch 没有解除分配
【发布时间】:2025-08-12 20:10:01
【问题描述】:

这是我之前的问题的重新发布,但由于编辑太多并且我已经简化了我的示例,我认为如果我创建一个新问题而不是多次重新编辑问题会更清楚。

问题:
UISwitch 对象以某种方式不会释放,即使没有对其进行任何处理。


项目:
只有两个视图控制器。 VC1 和 VC2。 VC1 有一个按钮来呈现 VC2。 VC2 包含一个关闭自身的按钮和一个自定义 UISwitchUILabelUIStepper 的属性。

VC1:

class VC1: UIViewController {

    let button = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(button)

        button.addTarget(self, action: #selector(open), for: .touchUpInside)

        // Some auto layout (not relevant to the question)
    }

    func open() { present(VC2(), animated: true) }
}

VC2:

class VC2: UIViewController {

    let button = UIButton()

    let shifty = CustomSwitch()    // Note: nothing has been done with this
    let labels = CustomLabels()
    let steppy = CustomSteppy()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(button)

        button.addTarget(self, action: #selector(close), for: .touchUpInside)

        // Some auto layout (not relevant to the question)
    }

    func close() { dismiss(animated: true) }
}

子类:

class CustomSwitch: UISwitch  { deinit { print("Switch has been deinitialized") } }
class CustomLabels: UILabel   { deinit { print("Labels has been deinitialized") } }
class CustomSteppy: UIStepper { deinit { print("Steppy has been deinitialized") } }

我创建这些子类的唯一原因是我可以在分析器中更轻松地跟踪它们。即使我不继承 UISwitch,也会发生同样的情况。

编辑:
我在子类中添加了deinitUILabelUIStepper 都显示了消息:

Labels has been deinitialized
Steppy has been deinitialized

所以UISwitch 似乎没有被取消初始化。

屏幕截图:
在这个屏幕截图中,我多次打开和关闭了 VC2。在那里,您可以看到只有对象 CustomSwitch 保持持久性,而 CustomLabelsCustomSteppy 已按原样释放。

正如 Rmaddy 所建议的,我想创建一个新问题的原因也是引用计数的结果。我已经对 SO 进行了一些解释,但我不太确定该怎么做。


问题:
为什么这个 UISwitch 会有这样的行为,我该如何解决这个问题?

【问题讨论】:

  • 您是否按照我上一个问题的建议进行操作?提醒一下,检查 Instruments 中的“Record Reference Counts”复选框并再次配置应用程序。然后看看是什么维护了对每个开关的引用。
  • @rmaddy 抱歉,是的,我已经完成了,但我忘了添加这些屏幕截图。我不知道该怎么做,因为我现在真的很困惑。尝试并搜索修复它,但仍然没有运气。
  • 它显示计数为+0。这意味着它应该被释放。你是在真机还是模拟器上测试?对于这类事情,我不相信模拟器。
  • @rmaddy 我正在 iPad、iPhone 和模拟器上测试它。屏幕截图来自 iPad 上的测试。如果 rfcount 为 +0,那么第一个屏幕截图上的“持久”计数意味着什么?如果我继续打开和关闭 VC2,持久字节会越来越高。
  • @rmaddy 为子类添加了 deinit 消息,正如预期的那样,只有 UISwitch 不会打印出 deinit 消息。

标签: swift swift3 uiswitch persistent


【解决方案1】:

这(最终)在 iOS 10.2 中得到修复

【讨论】: