1. 常见的业务场景
在iOS开发过程中,有很多时候,开发者需要将ViewController对象a添加到另一个ViewController对象b中,此时称a为b的childViewController,如下代码所示,
class BViewController: UIViewController {
override func viewDidLoad() {
let aVC = AViewController()
self.view.addSubview(aVC.view)
self.addChildViewController(aVC)
}
}
这样的写法存在一个潜在的问题,那就是当添加多个子控制器到父控制器,例如网易新闻客户端的首页,在不同的子控制器切换的时候,子控制器的-viewWillAppear
不执行。究其原因,当我们使用-addSubview
和-addChildViewController
添加子控制器时,是不正确或不完整的添加方式,因为-addSubview
和-addChildViewController
能保证子控制器的-viewDidLoad
和-viewWillAppear
执行一次,并不能保证-viewWillAppear
在子控制器展示的时候都执行。
2. 解决子控制器-viewWillAppear
不执行的问题
class BViewController: UIViewController {
override func viewDidLoad() {
let aVC = AViewController()
aVC.beginAppearanceTransition(true, animated: false)
self.view.addSubview(aVC.view)
childVC.endAppearanceTransition()
childVC.didMove(toParentViewController: self)
}
}
3. 代码优化
为了不重复造轮子,建议将该功能封装起来,方便以后调用。在swift中,将上述代码封装为UIViewController的extension方法,是一个不错的选择,如下代码所示,
import UIKit
extension UIViewController {
func addChildViewController(_ childVC: UIViewController, toView: UIView) {
childVC.beginAppearanceTransition(true, animated: false)
toView.addSubview(childVC.view)
childVC.endAppearanceTransition()
childVC.didMove(toParentViewController: self)
}
}
当开发者需要添加子视图控制器到父控制器时,即可简单调用,如下代码,
class BViewController: UIViewController {
override func viewDidLoad() {
let aVC = AViewController()
self.addChildViewController(aVC, toView: self.view)
}
}
这样,父控制器就合理有效地管理子控制器的生命周期,当多个子控制器相互切换时,对应的子控制器的生命周期方法会有效执行。