Swift - 詳解iOS的presentViewController

一翼馆、用途和相關(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>

  1. presenting VC
  2. presenting VC 的父VC
  3. presenting VC 所屬的container VC
  4. 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.

原地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市趁怔,隨后出現(xiàn)的幾起案子示括,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)存璃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人洒扎,你說(shuō)我怎么就攤上這事岂傲。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵习贫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)氯葬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任杏瞻,我火速辦了婚禮砌函,結(jié)果婚禮上仍劈,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布睛驳。 她就那樣靜靜地躺著爪瓜,像睡著了一般薄货。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巧涧,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天艺演,我揣著相機(jī)與錄音,去河邊找鬼肿男。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嘹承,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哟楷,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崭别!你這毒婦竟也來(lái)了土榴?” 一聲冷哼從身側(cè)響起坯台,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤撤摸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后褒纲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體准夷,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年莺掠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衫嵌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彻秆,死狀恐怖楔绞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唇兑,我是刑警寧澤酒朵,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站扎附,受9級(jí)特大地震影響蔫耽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜留夜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一针肥、第九天 我趴在偏房一處隱蔽的房頂上張望饼记。 院中可真熱鬧,春花似錦慰枕、人聲如沸具则。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)博肋。三九已至,卻和暖如春蜂厅,著一層夾襖步出監(jiān)牢的瞬間匪凡,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工掘猿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留病游,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓稠通,卻偏偏與公主長(zhǎng)得像衬衬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子改橘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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