一翼馆、用途和相關(guān)概念
iOS中顯示ViewController的方式有兩種push和modal割以,modal也叫模態(tài),模態(tài)顯示VC是iOS的重要特性之一应媚,其主要用于有以下場(chǎng)景:
- 收集用戶(hù)輸入信息
- 臨時(shí)呈現(xiàn)一些內(nèi)容
- 臨時(shí)改變工作模式
- 相應(yīng)設(shè)備方向變化(用于針對(duì)不同方向分別是想兩個(gè)ViewController的情況)
- 顯示一個(gè)新的view層級(jí)
這些場(chǎng)景都會(huì)暫時(shí)中斷APP的正常執(zhí)行流程严沥,主要作用是收集信息以及顯示一些重要的提示等。
presenting view controller & presented view controller
當(dāng)VCA模態(tài)的彈出了VCB中姜,那么VCA就是presenting view controller消玄,VCB就是presented view controller跟伏,具體在代碼中體現(xiàn)如下:
[VCA presentViewController:VCB animated:YES completion:nil];
1
container view controller
container view controller 指的是VC的容器類(lèi)翩瓜,通過(guò)container view controller兔跌,我們可以很方便的管理子VC,實(shí)現(xiàn)VC之間的跳轉(zhuǎn)等华望,iOS中container view controller包括g UINavigationController, UISplitViewController, 以及 UIPageViewController.
二赖舟、ModalPresentationStyle & Presentation Context
ModalPresentationStyle
presented VC 的modalPresentationStyle屬性決定了此次presentation的行為方式及UIKit尋找presentation context的方法宾抓,iOS提供了以下幾種常用的presentation style:
UIModalPresentationFullScreen
UIKit默認(rèn)的presentation style裕偿。 使用這種模式時(shí),presented VC的寬高與屏幕相同嘿棘,并且UIKit會(huì)直接使用rootViewController做為presentation context鸟妙,在此次presentation完成之后,UIKit會(huì)將presentation context及其子VC都移出UI棧花椭,這時(shí)候觀察VC的層級(jí)關(guān)系矿辽,會(huì)發(fā)現(xiàn)UIWindow下只有presented VC.
UIModalPresentationPageSheet
在常規(guī)型設(shè)備(大屏手機(jī)郭厌,例如plus系列以及iPad系列)的水平方向,presented VC的高為當(dāng)前屏幕的高度宾娜,寬為該設(shè)備豎直方向屏幕的寬度前塔,其余部分用透明背景做填充。對(duì)于緊湊型設(shè)備(小屏手機(jī))的水平方向及所有設(shè)備的豎直方向华弓,其顯示效果與UIModalPresentationFullScreen相同。
UIModalPresentationFormSheet
在常規(guī)型設(shè)備的水平方向慌洪,presented VC的寬高均小于屏幕尺寸冈爹,其余部分用透明背景填充欧引。對(duì)于緊湊型設(shè)備的水平方向及所有設(shè)備的豎直方向,其顯示效果與UIModalPresentationFullScreen相同
UIModalPresentationCurrentContext
使用這種方式present VC時(shí)憋肖,presented VC的寬高取決于presentation context的寬高岸更,并且UIKit會(huì)尋找屬性definesPresentationContext為YES的VC作為presentation context膊升,具體的尋找方式會(huì)在下文中給出 廓译。當(dāng)此次presentation完成之后,presentation context及其子VC都將被暫時(shí)移出當(dāng)前的UI棧瓜挽。
UIModalPresentationCustom
自定義模式征绸,需要實(shí)現(xiàn)UIViewControllerTransitioningDelegate的相關(guān)方法管怠,并將presented VC的transitioningDelegate 設(shè)置為實(shí)現(xiàn)了UIViewControllerTransitioningDelegate協(xié)議的對(duì)象排惨。
UIModalPresentationOverFullScreen
與UIModalPresentationFullScreen的唯一區(qū)別在于暮芭,UIWindow下除了presented VC,還有其他正常的VC層級(jí)關(guān)系辕宏。也就是說(shuō)該模式下瑞筐,UIKit以rootViewController為presentation context聚假,但presentation完成之后不會(huì)講rootViewController移出當(dāng)前的UI棧。
UIModalPresentationOverCurrentContext
尋找presentation context的方式與UIModalPresentationCurrentContext相同峭范,所不同的是presentation完成之后纱控,不會(huì)將context及其子VC移出當(dāng)前UI棧菜秦。但是球昨,這種方式只適用于transition style為UIModalTransitionStyleCoverVertical的情況(UIKit默認(rèn)就是這種transition style)。其他transition style下使用這種方式將會(huì)觸發(fā)異常闹获。
UIModalPresentationBlurOverFullScreen
presentation完成之后避诽,如果presented VC的背景有透明部分璃谨,會(huì)看到presented VC下面的VC會(huì)變得模糊,其他與UIModalPresentationOverFullScreen模式?jīng)]有區(qū)別底扳。
present VC是通過(guò)UIViewController的presentViewController: animated:completion:
函數(shù)實(shí)現(xiàn)的,在探討他們之間的層級(jí)關(guān)系之前鹊汛,我們首先要理解一個(gè)概念,就是presentation context滥嘴。
-
presentation context
presentation context是指為本次present提供上下文環(huán)境的類(lèi)若皱,需要指出的是走触,presenting VC通常并不是presentation context泥耀,Apple官方文檔對(duì)于presentation context的選擇是這樣介紹的:
When you present a view controller, UIKit looks for a view controller that provides a suitable context for the presentation. In many cases, UIKit chooses the nearest container view controller but it might also choose the window’s root view controller. In some cases, you can also tell UIKit which view controller defines the presentation context and should handle the presentation.
1
從上面的介紹可以看出痰催,當(dāng)我們需要present VC的時(shí)候夸溶,除非我們指定了context,否則UIKit會(huì)優(yōu)先選擇presenting VC所屬的容器類(lèi)做為presentation context扫皱,如果沒(méi)有容器類(lèi)韩脑,那么會(huì)選擇rootViewController段多。但是壮吩,UIKit搜索context的方式還與presented VC的modalPresentationStyle屬性有關(guān)鸭叙,當(dāng)modalPresentationStyle為UIModalPresentationFullScreen沈贝、UIModalPresentationOverFullScreen等模式時(shí),UIKit會(huì)直接選擇rootViewController做為context市俊。當(dāng)modalPresentationStyle為UIModalPresentationOverCurrentContext滤奈、UIModalPresentationCurrentContext模式時(shí)蜒程,UIKit搜索context的方式如下:
UIModalPresentationOverCurrentContext昭躺、UIModalPresentationCurrentContext模式下伪嫁,一個(gè)VC能否成為presentation context 是由VC的definesPresentationContext屬性決定的张咳,這是一個(gè)BOOL值脚猾,默認(rèn)UIViewController的definesPresentationContext屬性值是NO龙助,而 container view controller的definesPresentationContext默認(rèn)值是YES军援,這也是上文中,UIKit總是將container view controller做為presentation context的原因胸哥。如果我們想指定presenting VC做為context烘嘱,只需要在presenting VC的viewDidLoad方法里添加如下代碼即可:
self.definesPresentationContext = YES
1
UIKit搜索presentation context的順序?yàn)椋?/p>
- presenting VC
- presenting VC 的父VC
- presenting VC 所屬的container VC
- rootViewController
還有另外一種特殊情況蝇庭,當(dāng)我們?cè)谝粋€(gè)presented VC上再present一個(gè)VC時(shí)哮内,UIKit會(huì)直接將這個(gè)presented VC做為presentation context纹因。
三瞭恰、presenting VC 與presented VC 之間的層級(jí)關(guān)系
在iOS 中惊畏,presented VC 總是與 presentation context 處于同一層級(jí)颜启,而與presenting VC所在的層級(jí)無(wú)關(guān)缰盏,且同一個(gè)presentation context同時(shí)只能有一個(gè)presented VC口猜。
下面我們通過(guò)代碼來(lái)驗(yàn)證這個(gè)結(jié)論暮的。首先新建一個(gè)APP冻辩,各VC之間的層級(jí)關(guān)系如下:
在SecondContentVC中present FirstPresentVC,代碼如下:
FirstPresentVC *vc = [[FirstPresentVC alloc] init];
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:vc animated:YES completion:nil];
1
2
3
為了更好的觀察各VC的層級(jí)關(guān)系恨闪,我們將presented VC 的modalPresentationStyle屬性設(shè)置為UIModalPresentationOverCurrentContext放坏,這咙咽。然后我們?cè)倏锤鱒C之間的層級(jí)關(guān)系:
可以看到FirstPresentVC 與 SecondContentVC的navigationViewController處在同一層級(jí),說(shuō)明這時(shí)的presentation context是navigationViewController淤年。下面我們?cè)贔irstContentVC的viewDidLoad方法里添加如下代碼:
self.definesPresentationContext = YES;
1
彈出FirstPresentVC后再看VC之間的層級(jí)關(guān)系:
可以看到钧敞,F(xiàn)irstPresentVC 與 FirstContentVC 處在同一層級(jí),說(shuō)明此時(shí)的presentation context為FirstContentVC.
下面我們將SecondContentVC的definesPresentationContext屬性設(shè)為YES麸粮,然后觀察彈出FirstPresentVC之后的層級(jí)關(guān)系:
可以看到溉苛,此時(shí)的presentation context為SecondContentVC。這個(gè)實(shí)驗(yàn)也驗(yàn)證了UIKit 搜索presentation context的順序弄诲。
四愚战、ModalTransitionStyle
modalTransitionStyle可以設(shè)置presentation的轉(zhuǎn)場(chǎng)動(dòng)畫(huà),官方提供了幾種不同的轉(zhuǎn)場(chǎng)動(dòng)畫(huà),默認(rèn)是UIModalTransitionStyleCoverVertical寂玲。如果想要使用別的style塔插,只需要設(shè)置presented VC的modalTransitionStyle屬性即可彰檬。其余三種包括UIModalTransitionStyleFlipHorizontal、UIModalTransitionStyleCrossDissolve较雕、UIModalTransitionStylePartialCurl.具體每種style的表現(xiàn)形式參考Demo.