【问题标题】:iOS swift: Deint a child ViewControlleriOS swift:定义一个子 ViewController
【发布时间】:2018-11-05 02:42:02
【问题描述】:

我在 ViewController 中有一个 UITabBar。选择标签栏项目我添加不同的子视图控制器。并删除其他人。

但我从未在控制台上看到 deint 日志,只有 viewWillDisappear..

如何确定子视图控制器的定义以节省内存?

这就是我创建子控制器的方式:

private lazy var lotteryViewController: LotteryViewController = {
        // Load Storyboard
        let storyboard = UIStoryboard(name: "TrophyRoom", bundle: Bundle.main)

        // Instantiate View Controller
        var viewController = storyboard.instantiateViewController(withIdentifier: "LotteryViewController") as! LotteryViewController

        // Add View Controller as Child View Controller
        self.add(asChildViewController: viewController)

        return viewController
    }()

添加子控制器:

private func add(asChildViewController viewController: UIViewController) {
        // Add Child View Controller
        addChildViewController(viewController)

        // Add Child View as Subview
        containerView.addSubview(viewController.view)

        // Configure Child View
        viewController.view.frame = containerView.bounds
        viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        // Notify Child View Controller
        viewController.didMove(toParentViewController: self)
    }

从父viewController调用的remove方法:

private func remove(asChildViewController viewController: UIViewController) {
        // Notify Child View Controller
        viewController.willMove(toParentViewController: nil)

        // Remove Child View From Superview
        viewController.view.removeFromSuperview()

        // Notify Child View Controller
        viewController.removeFromParentViewController()
    }

子控制器的日志方法:

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        print("Sessions View Controller Will Appear")
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        print("Sessions View Controller Will Disappear")
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
        // Log if a view controller is being deinited
        print("\nDeinit: \(self.description)\n")
    }

【问题讨论】:

  • 你为什么期待 deinit 的日志?您是否实现了自己的 deinit 方法并在那里记录了一些内容?
  • 是的,当然,我有带打印功能的 deint 方法
  • 使用 Instruments 找出视图控制器是否泄漏以及是什么保留了它。
  • 如何创建视图控制器并将其添加到父视图?确保没有引用视图控制器的变量。
  • 那么lotteryViewController 不是我们所说的保留引用吗?

标签: ios swift memory-management uiviewcontroller


【解决方案1】:

类实例内存管理通过保留引用的计数来工作。 deinit 的意思是“这个对象即将不复存在,因为没有更多对它的保留引用”。

当您添加子视图控制器和删除子视图控制器时,您正在正确地进行父子“跳舞”。所以从这个角度来看一切都很好。当您调用viewController.removeFromParentViewController 时,确实 one 对它的保留引用消失了,即父子保留引用(childControllers 数组,已删除并释放子) .

但这并不意味着所有保留引用消失。事实上,deinit 不被称为 这一事实表明存在一些 other 保留引用。你现在要做的就是找出那个参考是什么。但事实上,您似乎已经向我们展示了它是什么:

private lazy var lotteryViewController: LotteryViewController = {
    let storyboard = UIStoryboard(name: "TrophyRoom", bundle: Bundle.main)
    var viewController = storyboard.instantiateViewController(withIdentifier: "LotteryViewController") as! LotteryViewController
    self.add(asChildViewController: viewController)
    return viewController
}()


lotteryViewController 是对子视图控制器的强(保留)引用。因此,即使在您将其作为孩子移除之后,它也可以使该视图控制器保持活动状态。

因此,您的体系结构存在弱点(或至少是一个意想不到的后果)(我的意思是您好奇地使用带有定义和调用初始化程序的 lazy var 实例属性)。制作子视图控制器的方法是实例化视图控制器,将其作为子视图交给父视图控制器,然后放开视图控制器,这样对它的唯一引用就是父视图。 (如果您需要对孩子的后续引用,您总是可以通过父母获得它。)您没有这样做,所以当孩子是时您不会获得deinit从父级中删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2023-03-13
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    相关资源
    最近更新 更多