關(guān)于addChildViewController

addChildViewController:給控制器添加子控制器

?愛喝農(nóng)藥de清涼?關(guān)注

?0.4?2018.04.29 16:17?字?jǐn)?shù) 211?閱讀 2318評論 4喜歡 3

用處:標(biāo)簽展示 () 等

好處:

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)存釋放機制

使用步驟:

1.addChildViewController:的同時調(diào)用addSubView:

[selfaddChildViewController:sfViewControllr];[self.view addSubview:sfViewControllr.view];

2.設(shè)置子視圖的位置级解,并顯示出來

sfViewControllr.view.frame =CGRectMake(0,300,1,1);[sfViewControllr didMoveToParentViewController:self];

3.移除子視圖

[sfViewControllr willMoveToParentViewController:nil];[sfViewControllr removeFromParentViewController];[sfViewControllr.view removeFromSuperview];

可能遇到的問題:

如果在子Controller中冒黑,把自己從父Controller中移除,在ios6中沒問題勤哗,在iOS7中抡爹,會崩潰

[self willMoveToParentViewController:nil];

[self.view removeFromSuperview];

[self removeFromParentViewController]; //ios7中崩潰

暫時的解決方法,在子Controller中發(fā)通知俺陋,通知父Controller豁延,移除子Controller


學(xué)習(xí)筆記:addChildViewController

?小曼blog?關(guān)注

?0.1?2018.11.28 11:55*?字?jǐn)?shù) 1098?閱讀 193評論 0喜歡 1

說來慚愧,蘋果在ios5就提供了addChildViewController這一方法腊状,而我卻一直沒有使用過诱咏,也對它不甚了解,這次有機會用用映屋,仔細學(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(iOS5.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。


iOS AddChildViewController遇到的問題

wwwwwwdi?關(guān)注

?0.6?2019.01.10 16:40*?字?jǐn)?shù) 578?閱讀 1028評論 0喜歡 4

今天在項目中檢查循環(huán)引用問題的時候遇到了此問題诫咱,查詢了別的頁面笙隙,發(fā)現(xiàn)打印log并不一樣。所以查閱了資料坎缭,這里記錄一下竟痰。

很多時候,我們都會遇到掏呼,在一個viewController中坏快,添加別的controller,已達到特殊的轉(zhuǎn)場效果憎夷,或者為了用戶能在一個頁面看到并和多個頁面的內(nèi)容交互的效果假消。

因此,蘋果給我們提供了這個概念岭接,和實現(xiàn)方法:addChildViewController

這里有一個使用場景富拗,

頁面初始化的時候臼予,在viewDidLoad中添加了子控制器,此時先加載緩存數(shù)據(jù)(也就是頁面會先展示)

然后展示的同時啃沪,重新調(diào)用接口粘拾,拉取數(shù)據(jù)。

得到數(shù)據(jù)之后创千,重新刷新頁面

相信大部分人也都是這么實現(xiàn)的缰雇。

因此,demo中是這么寫的:

A(ViewController)頁面中有一個按鈕追驴,跳轉(zhuǎn)到B(TestViewController)頁面, 然后B頁面中有兩個按鈕械哟,第一個按鈕用來第一次添加childViewController->C頁面(SecViewController), 第二個頁面,用來模擬網(wǎng)絡(luò)請求得到結(jié)果之后殿雪,重新刷新布局的操作暇咆。

這里有一個上述操作打印的log圖

可以看到中間很醒目的dealloc!此處就造成了我的疑惑

然后來看下containerViewController中是怎么實現(xiàn)的:

//TestViewController.m- (void)configureWithData:(NSArray*)array{if(!array.count)return;NSLog(@"~~~~~~~~~~~~~~~~~~~~%@ ---- %@ 前",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd));? ? [self.childViewControllers makeObjectsPerformSelector:@selector(removeFromParentViewController)];NSLog(@"~~~~~~~~~~~~~~~~~~~~%@ ---- %@ 后",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd));? ? ? ? [array enumerateObjectsUsingBlock:^(id_Nonnull obj,NSUIntegeridx,BOOL* _Nonnull stop) {? ? ? ? SecViewController *listVC = [[SecViewController alloc] init];? ? ? ? listVC.view.frame =self.view.bounds;? ? ? ? listVC.parentContainerViewController =self;? ? ? ? [selfaddChildViewController:listVC];//? ? ? ? [listVC didMoveToParentViewController:self];}];}

此方法在重新布局UI的時候調(diào)用丙曙。

可以看到爸业;其中有一句

[self.childViewControllers makeObjectsPerformSelector:@selector(removeFromParentViewController)];

此處記錄一下:

蘋果官方文檔中是這么描述的:

### Removing a Child View ControllerTo remove a child view controller from your content, remove theparent-child relationship between the view controllers by doing the following:1.Call the child’s `[willMoveToParentViewController:](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621381-willmovetoparentviewcontroller)` method with the value `nil`.2.Remove any constraints that you configured with the child’s root view.3.Remove the child’s root view from your container’s view hierarchy.4.Call the child’s `[removeFromParentViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621425-removefromparentviewcontroller)` method to finalize the end of the parent-child relationship.Removing a child view controller permanently severs the relationship betweenparentandchild. Remove a child view controller only when you no longer need to refer to it.Forexample, a navigation controller does not remove its current child view controllers when anewone is pushed onto the navigation stack. It removes them only when they are popped off the stack.

大致意思就是:

如果想要移除一個子控制器,需要自控制器調(diào)用willMoveToParentViewController, 移除子控制器view在父視圖中的位置約束亏镰,從父容器的層級中移除子控制器扯旷,然后調(diào)用子控制器的removeFromParentViewController。

此種操作索抓,就會造成子控制器不再被引用钧忽,然后執(zhí)行了dealloc方法

所以逼肯,此處就會造成惰瓜, 在進入一個頁面的時候(默認(rèn)是只在dealloc處打印了,沒有在viewDidLoad處打雍嚎蟆),先看到了子控制器的dealloc

附?Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末备禀,一起剝皮案震驚了整個濱河市洲拇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌曲尸,老刑警劉巖赋续,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異另患,居然都是意外死亡纽乱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門昆箕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸦列,“玉大人租冠,你說我怎么就攤上這事∈磬停” “怎么了顽爹?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骆姐。 經(jīng)常有香客問我镜粤,道長,這世上最難降的妖魔是什么玻褪? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任肉渴,我火速辦了婚禮,結(jié)果婚禮上带射,老公的妹妹穿的比我還像新娘同规。我一直安慰自己,他們只是感情好庸诱,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布捻浦。 她就那樣靜靜地躺著,像睡著了一般桥爽。 火紅的嫁衣襯著肌膚如雪朱灿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天钠四,我揣著相機與錄音盗扒,去河邊找鬼。 笑死缀去,一個胖子當(dāng)著我的面吹牛侣灶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缕碎,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼褥影,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咏雌?” 一聲冷哼從身側(cè)響起凡怎,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赊抖,沒想到半個月后统倒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡氛雪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年房匆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浴鸿,死狀恐怖井氢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赚楚,我是刑警寧澤毙沾,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站宠页,受9級特大地震影響左胞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜举户,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一烤宙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俭嘁,春花似錦躺枕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至近她,卻和暖如春叉瘩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粘捎。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工薇缅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人攒磨。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓泳桦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親娩缰。 傳聞我的和親對象是個殘疾皇子灸撰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容