如何取消初始化子 UIViewController?

How do I deinitialize a child UIViewController?

我有几个 UIViewController 添加到内容视图中。调用我的删除函数后,我注意到子 UIViewControllerdeinit 函数没有被调用,除非我明确地将子 UIViewController 的值设置为 nil .

这是正确的行为还是我做错了什么?

func removeViewController(fromCell cell:UICollectionViewCell, at indexPath:IndexPath){
    guard let childViewController = currentViewControllers[indexPath] else { return  }
    print("remove view controller called")
    childViewController.willMove(toParent: nil)
    childViewController.view.removeFromSuperview()
    childViewController.removeFromParent()
    currentViewControllers[indexPath] = nil
    // recycledViewControllers.insert(childViewController)
} 

Apple's Documentation 说:

Swift handles the memory management of instances through automatic reference counting (ARC)...

Deinitializers are called automatically, just before instance deallocation takes place. You are not allowed to call a deinitializer yourself.

这基本上意味着您不能自己调用​​ deinit() 方法,除非对它们的 strong 引用为零,否则不会取消初始化。

问题是您有 两个 对子视图控制器的引用:

  • 父视图控制器自动维护的引用(childViewControllers,现代Swift中的children

  • 您自己添加的附加参考 (currentViewControllers)。

因此,您必须让 两者 在子视图控制器消失之前离开。这就是您的代码所做的:

childViewController.willMove(toParent: nil)
childViewController.view.removeFromSuperview()
childViewController.removeFromParent()
// now `childViewControllers` / `children` has let go

currentViewControllers[indexPath] = nil
// now `currentViewController` has let go

所以你本身没有做错任何事,除非你首先通过 currentViewControllers 添加了这个额外的强引用。但我明白你为什么这样做了:你想要一种方法来将索引路径与子视图控制器配对。

所以你可以接受你的方法,或者如果你真的想要,你可以将 currentViewControllers 设置为只有 weak 引用它的值(通过使用NSMapTable 而不是字典)。