iOS Child Controller

最近碰到一個(gè)問題是發(fā)現(xiàn)當(dāng)移除一個(gè)subview的時(shí)候鉴未,viewWillDisappear被調(diào)用裙盾,但是viewDidDisappear卻沒有被調(diào)用薯鼠,導(dǎo)致注冊(cè)的通知沒有被注銷馋没,進(jìn)而引發(fā)一系列的錯(cuò)誤調(diào)用。趁此機(jī)會(huì)理清了一下有關(guān)"Child View Controller"的一些概念以及正確的調(diào)用方法袁波。

Child View Controller

官方手冊(cè)UIViewControler定義了 "View Controller"的主要職責(zé)瓦阐,包括:更新視圖內(nèi)容;響應(yīng)用戶操作篷牌;調(diào)整視圖尺寸以及控制頁(yè)面布局。

對(duì)于我們這個(gè)Case中使用孩子視圖控制器的行為在手冊(cè)中叫做"Container View Controller"踏幻,定義為:

A container view controller manages the presentation of content of other view controllers it owns, also known as its child view controllers

A child'??s view can be presented as-is or in conjunction with views owned by the container view controller.

引入addChildViewController事實(shí)上是為了更好的管理addSubView: 使得ViewViewController可以一一對(duì)應(yīng)枷颊,可以使用多Controller從而避免混在一起,可以在暫時(shí)不需要顯示視圖的時(shí)候不載入该面,而等到需要的時(shí)候再在家夭苗,并且通過這個(gè)還可以更加方便的進(jìn)行視圖切換,減少代碼耦合隔缀。(于此對(duì)應(yīng)题造,iOS5之前,即使不顯示猾瘸,所有的view也都被加載在內(nèi)存中)

ViewController容器篇這篇文章的總結(jié)蠻好界赔,介紹了addChildViewController相關(guān)的API的使用規(guī)則:

//添加
[self addChildViewController: _currentVC];
//[_currentVC willMoveToParentViewController: self];(自動(dòng)調(diào)用  省略)
//[_currentVC didMoveToParentViewController: self]; (可省略)

//移除
[_currentVC willMoveToParentViewController: nil];
[_currentVC removeFromParentViewController];
//[_currentVC didMoveToParentViewController: nil]; (自動(dòng)調(diào)用 省略)

//轉(zhuǎn)換
[_currentVC willMoveToParentViewController: nil];
[self transitionFromViewController: _currentVC toViewController: _secondVC];
[_secondVC didMoveToParentViewController: self];

//轉(zhuǎn)換子視圖控制器
- (void)transitionFromOldViewController:(UIViewController *)oldViewController toNewViewController:(UIViewController *)newViewController{
    [self transitionFromViewController:oldViewController toViewController:newViewController duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) {
        if (finished) {
            [newViewController didMoveToParentViewController:self];
            _currentVC = newViewController;
        }else{
            _currentVC = oldViewController;
        }
    }];
}

使用轉(zhuǎn)換時(shí),不需要移除"Child View Controller"牵触,保持多個(gè)"Child View Controller"淮悼,并在之間切換是這個(gè)功能的目的之一。需要注意的是如何使用"MoveTo"揽思,而這里有一個(gè)重要的益處就是不需要再手動(dòng)管理addSubView僅需在第一次初始化時(shí)使用袜腥,后面轉(zhuǎn)換時(shí)不需要。

為了檢測(cè)這些方法和孩子視圖控制器之間的調(diào)用映射钉汗,寫了下面的代碼進(jìn)行了測(cè)試:

var viewControllerOne:TestOneViewController? = TestOneViewController()
    
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
        
    NotificationCenter.default.addObserver(self, selector: #selector(clickAction), name:NSNotification.Name.UIApplicationWillResignActive, object: nil)
        
    if let currentViewController = viewControllerOne {
        self.addChildViewController(currentViewController)//加入self.childViewControllers, 不導(dǎo)致調(diào)用
        self.view.addSubview(currentViewController.view)//導(dǎo)致調(diào)用 viewWillAppear/viewDidAppear
        currentViewController.didMove(toParentViewController: self)
    }
}
    
func clickAction() {
    if let currentViewController = viewControllerOne {
        currentViewController.willMove(toParentViewController: nil)
        currentViewController.view.removeFromSuperview()//導(dǎo)致調(diào)用 viewWillDisappear/viewDidDisappear
        currentViewController.removeFromParentViewController()//移出self.childViewControllers, 不導(dǎo)致調(diào)用
        viewControllerOne = nil//導(dǎo)致調(diào)用 deinit
    }
}

可以總結(jié)說:添加或者刪除孩子視圖控制器的行為不會(huì)導(dǎo)致孩子視圖控制器的Action羹令,而添加或者刪除視圖會(huì)直接導(dǎo)致相應(yīng)的Action,而要保證孩子視圖占用內(nèi)存被及時(shí)釋放损痰,需要顯示注銷任何的引用福侈。

Navigation Controller

UINavigationController事實(shí)上就是一個(gè)"Container View Controller",而它提供了"Push/Pop"兩個(gè)方法來方便的添加和移除"Child View Controller"徐钠,可以直接翻譯成上面的添加移除代碼癌刽。

在"popViewController"模式下,是無法將最底層的"View Controller"也移除的,也就是至少保留一個(gè):


如果希望去除所有的"Child View Controller"显拜,可以通過重置viewControllers實(shí)現(xiàn)衡奥,另外一點(diǎn)需要注意的是,在這種情況下远荠,僅僅最上層的那個(gè)會(huì)調(diào)用"viewWillDisappear/viewDidDisappear":

從這里也會(huì)發(fā)現(xiàn)矮固,我們是不需要手動(dòng)調(diào)用removeFromSuperview的,這些可以自動(dòng)完成譬淳。

引用

Apple UIViewControler

ViewController容器篇

iOS addChildViewController方法

Custom Container View Controller

唐巧iOS5中UIViewController的新方法

How to remove UIViewControllers from stack so ViewDidDisappear is called?

iOS UINavigationController里的push和pop操作档址、抽屜效果原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市邻梆,隨后出現(xiàn)的幾起案子守伸,更是在濱河造成了極大的恐慌,老刑警劉巖浦妄,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尼摹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡剂娄,警方通過查閱死者的電腦和手機(jī)蠢涝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阅懦,“玉大人和二,你說我怎么就攤上這事《ィ” “怎么了惯吕?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)场晶。 經(jīng)常有香客問我混埠,道長(zhǎng),這世上最難降的妖魔是什么诗轻? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任钳宪,我火速辦了婚禮,結(jié)果婚禮上扳炬,老公的妹妹穿的比我還像新娘吏颖。我一直安慰自己,他們只是感情好恨樟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布半醉。 她就那樣靜靜地躺著,像睡著了一般劝术。 火紅的嫁衣襯著肌膚如雪缩多。 梳的紋絲不亂的頭發(fā)上呆奕,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音衬吆,去河邊找鬼梁钾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛逊抡,可吹牛的內(nèi)容都是我干的姆泻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼冒嫡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼拇勃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起孝凌,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤方咆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胎许,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峻呛,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年辜窑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寨躁。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡穆碎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出职恳,到底是詐尸還是另有隱情所禀,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布放钦,位于F島的核電站色徘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏操禀。R本人自食惡果不足惜褂策,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颓屑。 院中可真熱鬧斤寂,春花似錦、人聲如沸揪惦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽器腋。三九已至溪猿,卻和暖如春钩杰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诊县。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工讲弄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翎冲。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓垂睬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親抗悍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驹饺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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