說來慚愧,蘋果在ios5就提供了addChildViewController這一方法,而我卻一直沒有使用過,也對它不甚了解,這次有機會用用,仔細(xì)學(xué)習(xí)下。
方法定義
swift中,對應(yīng)的方法是:
/*
If the child controller has a different parent controller, it will first be removed from its current parent
by calling removeFromParentViewController. If this method is overridden then the super implementation must
be called.
大意是:如果被添加的VC已經(jīng)有父VC了,在調(diào)用這個方法之前會先從父VC中移除,然后再被添加到目前的VC上,做為目前VC的子VC。
*/
@available(iOS 5.0, *)
open func addChild(_ childController: UIViewController)
蘋果對這一方法的解釋:
This method creates a parent-child relationship between the current view controller and the object in the childController parameter. This relationship is necessary when embedding the child view controller’s view into the current view controller’s content. If the new child view controller is already the child of a container view controller, it is removed from that container before being added.
This method is only intended to be called by an implementation of a custom container view controller. If you override this method, you must call super in your implementation.
大意是:
這一方法在 當(dāng)前的VC 和 被添加的VC 之間創(chuàng)建了一種父-子的關(guān)系。當(dāng)把一個VC的view添加到當(dāng)前VC的view上的時候,就必須先使用addChild這個方法添加這種父子關(guān)系。如果子VC已經(jīng)有父VC了,那么調(diào)用該方法會先把子VC從之前的父VC中移除,然后再添加到當(dāng)前的VC上作為子VC。
這個方法只會在自定義的VC中被調(diào)用,如果打算重寫這個方法,則必須調(diào)用super的此方法。
也就是說,蘋果iOS5之后的API增加的 addChild(_ childController: UIViewController) 方法,并且希望我們在使用addSubview時,同時調(diào)用addChild(vc)方法將sub view對應(yīng)的viewController也加到當(dāng)前ViewController的管理中。
對于那些當(dāng)前暫時不需要顯示的subview,只通過addChild(_ childController: UIViewController)把subViewController加進去;需要顯示時再調(diào)用transitionFromViewController方法。將其添加進入底層的ViewController中。
這樣做的好處:
1.無疑,對頁面中的邏輯更加分明了。相應(yīng)的View對應(yīng)相應(yīng)的ViewController。
2.當(dāng)某個子View沒有顯示時,將不會被Load,減少了內(nèi)存的使用。
3.當(dāng)內(nèi)存緊張時,沒有Load的View將被首先釋放,優(yōu)化了程序的內(nèi)存釋放機制。
- 在iOS5中,ViewController中新添加了下面幾個方法:
- addChildViewController:
- removeFromParentViewController
- transitionFromViewController:toViewController:duration:options:animations:completion:
- willMoveToParentViewController:
- didMoveToParentViewController:
使用場景:
我們的日常開發(fā)中常有這樣一種需求,通過切換標(biāo)簽來切換不同的頁面,如果在一個 controller 管理這些 view 的話,代碼就顯得耦合度過高,也與 Apple 的 MVC 模式不符合,Apple 推薦一個 controller 管理一個 view。 同樣有人建議類似 [self.view addSubview:viewController.view] 的方式用另一個 controller 來控制,但是這樣會產(chǎn)生一個新的問題:直接 add 進去的subView不在 viewController的 view hierarchy 內(nèi),事件不會正常傳遞,如:旋轉(zhuǎn)、觸摸等,屬于危險操作違背CocoaTouch開發(fā)的設(shè)計MVC原則,viewController應(yīng)該且只應(yīng)該管理一個view hierarchy。同樣我們也要考慮另一個問題:這些子 view 大多數(shù)不會一直處于界面上,只是在某些情況下才會出現(xiàn),例如登陸失敗的提示 view,上傳附件成功的提示 view,網(wǎng)絡(luò)失敗的提示 view 等。但是雖然這些 view 很少出現(xiàn),但是我們卻常常一直把它們放在內(nèi)存中。
關(guān)于子VC的生命周期:
當(dāng)childViewController沒有被加到任何父視圖控制器時,如果把childViewController的view加到別的視圖上,viewWillAppear和viewDidAppear會正常調(diào)用。但是當(dāng)childViewController被加到一個父視圖控制器上后,viewWillAppear和viewDidAppear就會與父視圖控制器的viewWillAppear和viewDidAppear事件同步。
所以調(diào)用先后問題要注意:
先調(diào)用addSubView,viewWillAppear和viewDidAppear會各調(diào)用一次,再addChildViewController,與父視圖控制器的事件同步,即當(dāng)父視圖控制器的viewDidAppear調(diào)用時,childViewController的viewDidAppear方法會再調(diào)用一次。所以viewDidAppear方法被調(diào)用了兩次。
先調(diào)用addChildViewController,childViewController的事件與父視圖控制器同步,當(dāng)父視圖控制器的viewDidAppear調(diào)用時,childViewController的viewDidAppear方法會調(diào)用一次,再調(diào)用addSubView也不會觸發(fā)viewWillAppear和viewDidAppear。