iOS swift:Deint一个孩子ViewController

时间:2018-05-25 16:38:55

标签: ios swift memory-management uiviewcontroller

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

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

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

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

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

从父视图调用中删除的方法:

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")
    }

1 个答案:

答案 0 :(得分:3)

类实例内存管理通过保留引用的计数来工作。 deinit表示"此对象即将不存在,因为没有更多的保留引用"。

你正在做亲子"跳舞"添加子视图控制器和删除子视图控制器时正确。所以从这个角度来看一切都很好。当您致电viewController.removeFromParentViewController时,一个保留对它的引用肯定会消失,即父子保留引用(childControllers数组,已移除并且释放孩子)。

但这并不意味着所有保留引用都会消失。实际上,deinit 的事实表明某些其他保留引用存在。你现在要做的就是找出那个参考资料。但事实上,你似乎向我们展示了它是什么:

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当孩子从父母身上移走时。