在展示ViewController时,我希望视图生命周期符合以下顺序:
注意:4到5之间可以是viewWill / viewDidLayoutSubviews()的更多迭代。换句话说,我希望viewDidLayoutSubview在第一个viewDidAppear之前触发。
为了测试这个,我将一个childViewController添加到一个UIViewController子类,并调用addSubview来添加childViewController的视图。
override func viewDidLoad() {
super.viewDidLoad()
let childVC = ChildViewController()
self.addChildViewController(childVC)
self.view.addSubview(childVC.view)
}
当我打印出视图方法时,这会产生预期的结果:
当我在UIPageViewController子类上使用setViewController时:
override func viewDidLoad() {
super.viewDidLoad()
let childVC = ChildViewController()
self.setViewControllers([childVC], direction: .forward, animated: true, completion: nil)
}
我总是在第一个LayoutSubviews方法之前执行viewDidAppear:
有人可以解释为什么会出现这种情况吗?
----进一步观察---
我还在childViewController的日志中添加了willMove和DidMove方法。初步测试的结果:
willMove(toParentViewController:)
UIPageViewController的结果:
因此看起来好像setViewController调用了moveToParentViewController,这可能是它之前调用viewDidAppear的原因。
答案 0 :(得分:0)
setViewControllers
调用此方法:
/* @class UIPageViewController */
-(void)_setViewControllers:(void *)arg2 withCurlOfType:(long long)arg3 fromLocation:(struct CGPoint)arg4 direction:(long long)arg5 animated:(bool)arg6 notifyDelegate:(bool)arg7 completion:(void *)arg8 {
[r13 _child:r14 beginAppearanceTransition:rcx animated:r8];
r14 = [_objc_msgSend_1426728(r13, @selector(view)) retain];
rax = _objc_msgSend_1426728(var_D0, @selector(view));
rax = [rax retain];
[r14 addSubview:rax];
r13 = var_B8;
[rax release];
rdi = r14;
r14 = var_D0;
[rdi release];
[r13 _childEndAppearanceTransition:r14];
开始和结束看起来像这样:
/* @class UIPageViewController */
-(void)_child:(void *)arg2 beginAppearanceTransition:(bool)arg3 animated:(bool)arg4 {
r14 = arg4;
r15 = arg3;
r12 = [arg2 retain];
if ([self _forwardAppearanceMethods] == 0x0) {
objc_unsafeClaimAutoreleasedReturnValue([r12 view]);
[r12 beginAppearanceTransition:r15 & 0xff animated:r14 & 0xff];
}
[r12 release];
return;
}
如上所述,对_forwardAppearanceMethods
的调用必须返回0,这会引起问题,并查看其作用:
/* @class UIViewController */
-(bool)_forwardAppearanceMethods {
r14 = self;
rax = objc_opt_class(self, _cmd);
rbx = @selector(shouldAutomaticallyForwardAppearanceMethods);
rdx = rbx;
if ([rax doesOverrideViewControllerMethod:rdx] == 0x0) {
rbx = @selector(automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers);
}
rax = *_objc_msgSend;
rax = (rax)(r14, rbx, rdx, *_objc_msgSend);
return rax;
}
我们可以看到它的调用shouldAutomaticallyForwardAppearanceMethods
已实现为低位UIPageViewController
,如下所示:
/* @class UIPageViewController */
-(bool)shouldAutomaticallyForwardAppearanceMethods {
return 0x0;
}
请注意,它还具有:
/* @class UIPageViewController */
-(bool)shouldAutomaticallyForwardRotationMethods {
return 0x0;
}
使用Hopper
完成反编译