我已经实现了很多视图控制器容器,但完全正确地完成生命周期仍然很棘手。
添加子视图控制器的一般方法看起来很简单:
parent.addChildViewController(child)
(一次!)child.beginAppearanceTransition(true, animated: …)
(可能多次,在true
和false
之间轮流展开)view
添加到父级的视图层次结构中view
child.endAppearanceTransition()
(一次!)child.didMoveToParentViewController(parent)
(一次!)现在很少这么简单。例如,父视图控制器本身可能处于转换(viewWillAppear()
)中,因此必须延迟步骤5和6,直到父级也完成它的转换(viewDidAppear()
)。
情况可能更复杂。你可能不小心忘了打电话。或者孩子忘记拨打super.…()
。或者你多次调用一个方法,你不应该再次调用它。(
为了找到这样的bug,我在我的库中调用UIViewController
中的所有生命周期方法,以便它在日志中自动报告大量不同的生命周期错误。这就像一个魅力,我在自己的容器中发现了几个问题。但是我也收到了UIKit自己的视图控制器的几个报告,所以我现在质疑我是否真的了解预期的生命周期。
UIViewController.didMoveToParentViewController()
的文档例如:
如果要实现自己的容器视图控制器,则必须 调用子视图的
didMoveToParentViewController:
方法 转换到新控制器后的控制器完成或, 如果没有过渡,请立即拨打电话addChildViewController:
方法。
所以现在对我来说最重要的问题是:
方法willMoveToParentViewController()
和didMoveToParentViewController()
是否与view(Did|Will)(Appear|Disappear)
直接相关?
即如上面的文档摘录所述,在子视图控制器的转换完成之前,我不能调用didMoveToParentViewController()
。这意味着必须最后调用viewDidDisappear()
或viewDidAppear()
- viewWillAppear()
和viewWillDisappear()
。
UIKit似乎就是这样做的(在转换期间调用(will|did)MoveToParentViewController
),例如在iPhone上以模仿方式呈现UISplitViewController
UINavigationController
个孩子的时候:
VIEW CONTROLLER LIFECYCLE BROKEN for <UINavigationController: 0x7cc18a00>
Problem:
.willMoveToParentViewController() was called unexpectedly during an appearance transition. It must only be called while the view controller is in DidDisappear or DidAppear state.
Possible Causes:
- the view controller containment implementation of UISplitViewController or one if its parents is broken
VIEW CONTROLLER LIFECYCLE BROKEN for <UINavigationController: 0x7cc18a00>
Problem:
.didMoveToParentViewController() was called unexpectedly during an appearance transition. It must only be called while the view controller is in DidDisappear or DidAppear state.
Possible Causes:
- the view controller containment implementation of the parent view controller or one if its parents is broken
当呈现具有文本字段的UIAlertViewController
时,错误堆积起来:
VIEW CONTROLLER LIFECYCLE BROKEN for <_UIAlertControllerTextFieldViewController: 0x7dd84bb0>
Problem:
.willMoveToParentViewController() was called unexpectedly while view controller is in WillMoveToParent state.
Possible Causes:
- _UIAlertControllerTextFieldViewController or one of its superclasses called super.willMoveToParentViewController() multiple times
- _UIAlertControllerTextFieldViewController or one of its superclasses called super.willMoveToParentViewController() from within it's .didMoveToParentViewController()
- the view controller containment implementation of UIAlertController or one if its parents is broken
- it was already called implicitly by parent.addChildViewController(_UIAlertControllerTextFieldViewController) so you must not call it again
VIEW CONTROLLER LIFECYCLE BROKEN for <UICompatibilityInputViewController: 0x7a99fdb0>
Problem:
.didMoveToParentViewController(non-nil) was not called after .viewDidAppear() to complete an earlier .willMoveToParentViewController(non-nil).
Possible Causes:
- the view controller containment implementation of UIInputWindowController is likely broken
VIEW CONTROLLER LIFECYCLE BROKEN for <UICompatibilityInputViewController: 0x7dd67650>
Problem:
.didMoveToParentViewController(non-nil) was not called after .viewDidAppear() to complete an earlier .willMoveToParentViewController(non-nil).
Possible Causes:
- the view controller containment implementation of UICompatibilityInputViewController is likely broken
是否有人对如何进行视图控制器遏制有很好的了解?
这些只是UIKit中的错误还是这种行为&#34;可以接受&#34;?
如果有人对生命周期验证和&amp;错误报告工作可以查看this file。