When presenting a ViewController I expect the view lifecycle to be in the order:
- viewDidLoad()
- viewWillAppear
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewDidAppear()
note: between 4 and 5 can be more iterations of the viewWill/viewDidLayoutSubviews(). In other words I'd expect viewDidLayoutSubview to fire before the first viewDidAppear.
To test this, I add a childViewController to a UIViewController subclass and call addSubview to add the childViewController's view.
override func viewDidLoad() {
super.viewDidLoad()
let childVC = ChildViewController()
self.addChildViewController(childVC)
self.view.addSubview(childVC.view)
}
This produces the expected results when i print out the view methods:
- viewDidLoad()
- viewWillAppear
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewDidAppear
When I use setViewController on a UIPageViewController subclass:
override func viewDidLoad() {
super.viewDidLoad()
let childVC = ChildViewController()
self.setViewControllers([childVC], direction: .forward, animated: true, completion: nil)
}
I always get viewDidAppear performing before the first LayoutSubviews method:
- viewDidLoad()
- viewWillAppear
- viewDidAppear
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
Can someone explain why this behaviour occurs?
---- further observations ---
I've also added in a log for willMove and DidMove methods on the childViewController. The results for the initial test:
willMove(toParentViewController:)
- viewDidLoad()
- viewWillAppear
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewDidAppear
The results for the UIPageViewController:
- viewDidLoad()
- viewWillAppear
- viewDidAppear didMove(toParentViewController:)
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
- viewWillLayoutSubviews()
- viewDidLayoutSubviews()
So it looks as though the setViewController invokes a moveToParentViewController which perhaps may be the reason why it is invoking the viewDidAppear earlier.