ios - iOS swift:定义一个子 ViewController
问题描述
我在 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
意思是“这个对象即将不复存在,因为不再有对它的保留引用”。
当您添加子视图控制器和删除子视图控制器时,您正在正确地进行父子“跳舞”。所以从这个角度来看一切都很好。当您调用 时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
带有定义和调用初始化程序的实例属性的好奇使用)。制作子视图控制器的方法是实例化视图控制器,将其作为其子级交给父级,然后放开视图控制器,使对它的唯一引用是父级。(如果您需要对子项的后续引用,您始终可以通过 parent获取它。)您没有这样做,因此您不会得到deinit
子项从父项中删除的时间。
推荐阅读
- android - 如何在 react-native 中添加破折号或虚线边框?
- django - 基于 Celery 类的任务同步运行而不是异步运行
- c# - 尝试从 Opc 服务器获取历史数据时如何修复“BadServiceUnsupported”错误
- angular - Angular Material:树节点计数
- c++ - 完美转发 const ref 扣除错误
- kotlin - kotlin 表达式自动转换时
- outlook-redemption - 文件 [filepath].ost 正在使用中,升级到 Outlook 2016 后无法访问
- c# - 从存储库模拟返回 Null
- php - 更改 amCharts 中的甘特图,使列值是轴值,旧轴值是新列值?
- javascript - 如何将对象键重新排列到分组对象的开头