翻譯:iOS視圖控制器編程指南(八)——Present視圖控制器(Presenting a View Controller)

在屏幕上顯示視圖控制器有兩種方法:嵌入到容器視圖控制器中或者present這個視圖控制器伴澄。容器視圖控制器提供應(yīng)用的主要導(dǎo)航考余,但present視圖控制器同樣也是一個重要的導(dǎo)航工具菲茬。可以在當(dāng)前的視圖控制器上直接present一個新的視圖控制器愕秫。通常承疲,當(dāng)你希望實(shí)現(xiàn)modal界面時,可以present視圖控制器冲呢,但你也可以使用它們用于其他用途舍败。

UIViewController 類支持present視圖控制器,可用于所有的視圖控制器對象敬拓。你可以在任何其他視圖控制器上present任何一個視圖控制器邻薯,雖然UIKit可能重新路由該請求到不同的視圖控制器上。present視圖控制器會在原始視圖控制器之間創(chuàng)建關(guān)系乘凸,原始視圖控制器稱為 presenting view controller厕诡,顯示的新視圖控制器稱為presented view controller。這個關(guān)系是視圖控制器層級結(jié)構(gòu)的一部分营勤,直到presented視圖控制器被dismiss木人。

展示和過渡的過程

present一個視圖控制器是一種快速而簡單的方法在屏幕上推出新內(nèi)容信柿。UIKit內(nèi)置present機(jī)制冀偶,允許使用內(nèi)置或自定義動畫來顯示一個新的視圖控制器醒第。內(nèi)置present和動畫需要很少的代碼因?yàn)閁IKit處理了所有的工作。你也可以很容易的在任何視圖控制器創(chuàng)建自定義present和動畫进鸠。

你可以以編程方式或使用segue來發(fā)起視圖控制器的present稠曼。如果在設(shè)計(jì)時你知道應(yīng)用的導(dǎo)航,segue是發(fā)起present最簡單的方式客年。更多動態(tài)界面霞幅,或者沒有專門的控件發(fā)起segue的情況下,使用 UIViewController方法來present視圖控制器量瓜。

Presentation Styles

presentation style 是一個視圖控制器管理其屏幕上的外觀司恳。UIKit定義了許多標(biāo)準(zhǔn)的present風(fēng)格,每個都有特定的外觀和意圖绍傲。你也可以定義自定義present風(fēng)格扔傅。當(dāng)設(shè)計(jì)你的應(yīng)用時,為你的應(yīng)用選擇合適的present風(fēng)格烫饼,并為要present的視圖控制器的 modalPresentationStyle屬性分配適合的常數(shù)猎塞。

Full-Screen Presentation Styles

Full screen presentation styles覆蓋全部屏幕,防止與底層內(nèi)容互動杠纵。在水平常規(guī)環(huán)境中荠耽,只有full-screen styles完全覆蓋了底層內(nèi)容。其余變暗或有透明度的視圖允許部分底層視圖控制器顯示比藻。在水平緊湊環(huán)境中铝量,full-screen present方式自動采用UIModalPresentationFullScreen風(fēng)格并覆蓋所有底層內(nèi)容。

圖8-1 說明在水平常規(guī)環(huán)境使用UIModalPresentationFullScreen,UIModalPresentationPageSheetUIModalPresentationFormSheet風(fēng)格present方式的外觀银亲。在圖中慢叨,在左上角的綠色視圖控制器present在右上角的藍(lán)色視圖控制器,各種present風(fēng)格如下群凶。對于一些present風(fēng)格插爹,UIKit在兩個視圖控制器內(nèi)容之間插入一個半透明視圖。

圖8-1 全屏present風(fēng)格

注意

當(dāng)使用UIModalPresentationFullScreen風(fēng)格present一個視圖控制器時请梢,UIKit通常在完成過渡動畫后刪除底層視圖控制器的視圖赠尾。你可以通過指定UIModalPresentationOverFullScreen風(fēng)格防止刪除這些視圖。當(dāng)present的視圖控制器有透明區(qū)域讓底層內(nèi)容顯示時可以采用這種風(fēng)格毅弧。

當(dāng)使用一種present 風(fēng)格時气嫁,視圖控制器啟動的present必須覆蓋整個屏幕。如果將要present的視圖控制器不能覆蓋整個屏幕够坐,UIKit遍歷視圖控制器層級直到找到一個覆蓋整個屏幕的視圖控制器寸宵。如果不能找到一個中間視圖控制器充滿屏幕崖面,UIKit使用窗口的根視圖控制器。

The Popover Style

UIModalPresentationPopover風(fēng)格以彈出窗口的方式顯示在視圖控制器上梯影。popover用于顯示額外信息或項(xiàng)目列表中選中的對象巫员。在橫向常規(guī)環(huán)境中,popover視圖僅覆蓋屏幕的一部分甲棍,如圖8-2所示简识。在橫向緊湊環(huán)境中,popover默認(rèn)采用UIModalPresentationOverFullScreen present方式感猛。在popover視圖外點(diǎn)擊七扰, popover視圖將自動dismiss。

圖8-2 彈窗present風(fēng)格

因?yàn)樵谒骄o湊環(huán)境中陪白,popover采用full-screen 的present方式颈走,通常需要修改popover代碼處理適配。在full-screen模式咱士,需要一種方法dismiss掉present的popover立由。你可以通過添加一個按鈕,將popover嵌入到將要dismiss的容器視圖控制器司致,或者改變自適應(yīng)行為本身拆吆。

如何配置彈窗,參見在視圖控制器上present彈窗( Presenting a View Controller in a Popover)脂矫。

The Current Context Styles

UIModalPresentationCurrentContext 風(fēng)格在界面覆蓋了一個特殊的視圖控制器枣耀。當(dāng)使用contextual風(fēng)格,通過設(shè)置 definesPresentationContext屬性為YES庭再,指定要覆蓋的視圖控制器捞奕。圖8-3說明了current context 只覆蓋分屏視圖控制器的一個子視圖控制器。

圖8-3 當(dāng)前環(huán)境present風(fēng)格

注意

當(dāng)使用UIModalPresentationFullScreen風(fēng)格present一個視圖控制器拄轻,UIKit通常在過渡動畫完成后刪除底層視圖控制器的視圖颅围。可以設(shè)置UIModalPresentationOverCurrentContext風(fēng)格恨搓,防止刪除那些視圖院促。當(dāng)present的視圖控制器有透明區(qū)域讓底層內(nèi)容顯示時,可以使用該風(fēng)格斧抱。

定義視圖控制器還可以在present過程中定義過渡動畫常拓。通常,當(dāng)使用present視圖控制器的 modalTransitionStyle屬性辉浦,UIKit渲染視圖控制器到屏幕弄抬。如果present context視圖控制器的 providesPresentationContextTransitionStyle值設(shè)為YES,UIKit使用視圖控制器的modalTransitionStyle屬性代替宪郊。

當(dāng)過渡到水平緊湊的環(huán)境掂恕,current context風(fēng)格采用 UIModalPresentationFullScreen 風(fēng)格拖陆。為了改變該行為,使用自適應(yīng)present委托指定不同的present風(fēng)格或視圖控制器懊亡。

Custom Presentation Styles

UIModalPresentationCustom風(fēng)格使用自定義的風(fēng)格present視圖控制器依啰。創(chuàng)建一個自定義風(fēng)格包括子類化UIPresentationController ,使用其方法來渲染任何自定義視圖到屏幕上并設(shè)置present視圖控制器的大小和位置斋配。present控制器還處理由于視圖控制器的trait變化引起的適配孔飒。

如何定義自定義present視圖控制器的信息,參見創(chuàng)建自定義present( Creating Custom Presentations)艰争。

Transition Styles

Transition風(fēng)格決定用于顯示present視圖控制器的動畫類型。對于內(nèi)置transition風(fēng)格桂对,你可以為present視圖控制器的 modalTransitionStyle屬性指定一種標(biāo)準(zhǔn)transition風(fēng)格甩卓。當(dāng)present視圖控制器,UIKit創(chuàng)建相應(yīng)的動畫風(fēng)格蕉斜。例如逾柿,圖8-4說明了標(biāo)準(zhǔn)slide-up過渡(UIModalTransitionStyleCoverVertical)如何視圖控制器渲染到屏幕上。視圖控制器B開始在屏幕外宅此,并覆蓋到視圖控制器A上机错。當(dāng)dismiss視圖控制器B,動畫逆轉(zhuǎn)父腕,B下滑露出A弱匪。

圖8-4 視圖控制器的過渡動畫

可以使用動畫對象和過渡代理來創(chuàng)建自定義過渡。動畫對象為屏幕上放置的視圖控制器創(chuàng)建過渡動畫璧亮。過渡代理在合適的時間為UIKit提供動畫對象萧诫。更多關(guān)于如何實(shí)現(xiàn)自定義過渡的信息,參見自定義過渡動畫(Customizing the Transition Animations)枝嘶。

present和顯示一個視圖控制器

UIViewController類提供兩種方法來顯示一個視圖控制器:

  • showViewController:sender:showDetailViewController:sender:方法為顯示視圖控制器提供最大限度的適應(yīng)性和靈活性帘饶。這些方法讓present視圖控制器決定如何最好的處理present。例如群扶,容器視圖控制器可能合并視圖控制器作為子視圖控制器而不是以模態(tài)的方式present及刻。默認(rèn)以模態(tài)的方式present視圖控制器。
  • presentViewController:animated:completion: 方法總是以模態(tài)的方式顯示視圖控制器竞阐。視圖控制器調(diào)用這個方法可能不會最終處理present但總是以模態(tài)的方式present缴饭。在水平緊湊環(huán)境中,該方法采用該present風(fēng)格馁菜。

showViewController:sender:showDetailViewController:sender: 方法是啟動present的首選方法茴扁。視圖控制器可以調(diào)用它們,而不用知道任何關(guān)于視圖控制器層級結(jié)構(gòu)或當(dāng)前視圖控制器在層級結(jié)構(gòu)的位置汪疮。這些方法使重用視圖控制器更加容易峭火,而無需編寫條件代碼路徑毁习。

present視圖控制器

有幾種方法可以present視圖控制器:

  • 使用segue自動present視圖控制器。使用界面構(gòu)建器指定的信息卖丸,segue實(shí)例化并present視圖控制器纺且。關(guān)于如何配置segue的更多信息,參見使用segue( Using Segues)稍浆。
  • 使用 showViewController:sender:showDetailViewController:sender:方法顯示視圖控制器载碌。在自定義視圖控制器中,可以改變這些方法的行為使之更加適合你的視圖控制器衅枫。
  • 調(diào)用presentViewController:animated:completion:方法以模態(tài)的方式present視圖控制器嫁艇。

關(guān)于如何dismiss使用這些技術(shù)present的視圖控制的更多信息,參見dismiss一個presented的視圖控制器( Dismissing a Presented View Controller)弦撩。

顯示視圖控制器

當(dāng)使用和方法步咪,得到屏幕上一個新的視圖控制器的過程很簡單:

  1. 創(chuàng)建你希望present的視圖控制器對象。當(dāng)創(chuàng)建視圖控制器時益楼,你負(fù)責(zé)初始化它執(zhí)行任何所需的任何數(shù)據(jù)猾漫。
  2. 設(shè)置新視圖控制器的 modalPresentationStyle屬性是首選present風(fēng)格。該風(fēng)格可能不用于最終的present感凤。
  3. 設(shè)置視圖控制器的modalTransitionStyle屬性設(shè)置所需的過渡動畫風(fēng)格悯周。該風(fēng)格可能不用于最終的present。
  4. 調(diào)用當(dāng)前視圖控制器的 showViewController:sender:showDetailViewController:sender:方法陪竿。

UIKit轉(zhuǎn)發(fā)showViewController:sender:showDetailViewController:sender: 方法的調(diào)用給present視圖控制器禽翼。視圖控制器可以決定如何最好的執(zhí)行present,并且可以根據(jù)需呀改變present和過渡風(fēng)格萨惑。例如捐康,導(dǎo)航控制器可能push該視圖控制器到導(dǎo)航堆棧。

關(guān)于顯示視圖控制器和以模態(tài)的方式present視圖控制器的差異信息庸蔼,參見present和顯示視圖控制器( Presenting Versus Showing a View Controller)解总。

以模態(tài)的方式present視圖控制器

當(dāng)直接present視圖控制器,你需要告訴UIKit你希望視圖控制器如何顯示以及如何渲染到屏幕上姐仅。

創(chuàng)建你希望present的視圖控制器對象花枫。當(dāng)創(chuàng)建視圖控制器時,你負(fù)責(zé)初始化它執(zhí)行任何所需的任何數(shù)據(jù)掏膏。

  1. 設(shè)置新視圖控制器的 modalPresentationStyle 屬性為所需的present風(fēng)格劳翰。
  2. 設(shè)置視圖控制器的 modalTransitionStyle屬性為所需的動畫風(fēng)格。
  3. 調(diào)用當(dāng)前視圖控制器的 presentViewController:animated:completion:方法馒疹。

調(diào)用presentViewController:animated:completion: 方法的視圖控制器可能不是最終執(zhí)行模態(tài)present的視圖控制器佳簸。present風(fēng)格決定了視圖控制器如何被present,包括present視圖控制器所需的特征。例如生均,一個全屏present必須由一個全屏視圖控制器啟動听想。如果當(dāng)前present視圖控制器不合適,UIKit遍歷視圖控制器層級直到找到合適的马胧。完成模態(tài)present后汉买,UIKit更新受影響的視圖控制器的presentingViewControllerpresentedViewController屬性。

列表8-1 演示了如何以編程的方式present一個視圖控制器佩脊。當(dāng)用戶添加一個新視圖控制器蛙粘,應(yīng)用提示用戶輸入present導(dǎo)航視圖控制器的基本信息。被選中的導(dǎo)航控制器會在標(biāo)準(zhǔn)的地方放置一個取消和完成按鈕威彰。使用導(dǎo)航控制器使擴(kuò)展新界面更加容易出牧。你所需要做的是push新視圖控制器到導(dǎo)航堆棧。

列表8-1 以編程的方式present一個視圖控制器

<pre><code>

    • (void)add:(id)sender {
  1. // Create the root view controller for the navigation controller
  2. // The new view controller configures a Cancel and Done button for the
  3. // navigation bar.
  4. RecipeAddViewController *addController = [[RecipeAddViewController alloc] init];
  5. addController.modalPresentationStyle = UIModalPresentationFullScreen;
  6. addController.transitionStyle = UIModalTransitionStyleCoverVertical;
  7. [self presentViewController:addController animated:YES completion: nil];
  8. }
    </pre></code>

以彈窗形式present視圖控制器

在present視圖控制器之前抱冷,popover需要額外的配置崔列。在設(shè)置模態(tài)present風(fēng)格為 UIModalPresentationPopover后,配置一下popover相關(guān)屬性:

可以使用 UIPopoverPresentationController對象在需要時調(diào)整彈窗的外觀鱼响。彈窗present控制器還支持代理對象鸣剪,可以使用它來響應(yīng)在present過程中的變化。例如丈积,你可以使用代理來響應(yīng)彈窗在屏幕上出現(xiàn)筐骇、消失或重新定位。關(guān)于該對象的更多信息江滨,參見UIPopoverPresentationController類引用(UIPopoverPresentationController Class Reference)铛纬。

dismiss一個presented的視圖控制器

調(diào)用presenting視圖控制器的dismissViewControllerAnimated:completion:方法來dismiss一個presented的視圖控制器。你可以在presented視圖控制器本身的方法唬滑。當(dāng)presented視圖控制器調(diào)用該方法告唆,UIKit自動轉(zhuǎn)發(fā)請求到presenting視圖控制器。

在dismiss視圖控制器前保存任何重要信息晶密。dismiss視圖控制器會將其從視圖控制器層級結(jié)構(gòu)刪除并從屏幕上刪除視圖擒悬。如果在其他地方存儲的視圖控制器沒有強(qiáng)引用,dismiss該視圖控制器會釋放與之關(guān)聯(lián)的內(nèi)存稻艰。

如果presented視圖控制器必須返回?cái)?shù)據(jù)到presenting視圖控制器懂牧,使用 delegation 設(shè)計(jì)模式來完成傳遞。代理使應(yīng)用視圖控制器的重用更容易尊勿。使用代理僧凤,presented視圖控制器存儲代理對象的引用畜侦,實(shí)現(xiàn)正式protocol的方法。Presented視圖控制器在代理調(diào)用這些方法用于收集結(jié)果拼弃。在典型的實(shí)現(xiàn)中夏伊,presenting視圖控制器作為presented視圖控制器的代理。

present在不同storyboard種定義的視圖控制器

雖然在同一storyboard中的兩個視圖控制器之間可以創(chuàng)建segue吻氧,但在不同storyboard中不能創(chuàng)建segue溺忧。當(dāng)你希望顯示存儲在另一個storyboard中的視圖控制器時,你必須在present之前顯式的實(shí)例化該視圖控制器盯孙,如列表8-2所示鲁森。例子以模態(tài)的方式present視圖控制器,但你可以push它到導(dǎo)航控制器或以其他方式顯示振惰。

列表8-2 加載storyboard中的視圖控制器

<pre><code>

  1. UIStoryboard* sb = [UIStoryboard storyboardWithName:@"SecondStoryboard" bundle:nil];
  2. MyViewController* myVC = [sb instantiateViewControllerWithIdentifier:@"MyViewController"];
  3. // Configure the view controller.
  4. // Display the view controller
  5. [self presentViewController:myVC animated:YES completion:nil];
    </pre></code>

沒有要求你必須在應(yīng)用中創(chuàng)建多個storyboard歌溉。不過,在這里有一些情況下多個storyboard可能有用:

  • 你有一個大的編程團(tuán)隊(duì)骑晶,不同的用戶界面分配給團(tuán)隊(duì)的不同部分痛垛。每個團(tuán)隊(duì)擁有不同的storyboard文件以減少沖突。
  • 你購買或創(chuàng)建一個庫預(yù)定義了視圖控制器類型集合桶蛔;這些視圖控制器的內(nèi)容定義在庫中的storyboard中匙头。
  • 你有需要在屏幕外顯示的內(nèi)容。在這種情況下仔雷,你可能保持所有視圖控制器與單獨(dú)storyboard的視圖控制器相關(guān)蹂析。相同場景的另一種模式是編寫一個自定義segue。

官方原文地址:

https://developer.apple.com/library/prerelease/ios/featuredarticles/ViewControllerPGforiPhoneOS/PresentingaViewController.html#//apple_ref/doc/uid/TP40007457-CH14-SW1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碟婆,一起剝皮案震驚了整個濱河市电抚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌竖共,老刑警劉巖蝙叛,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肘迎,居然都是意外死亡甥温,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門妓布,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姻蚓,“玉大人,你說我怎么就攤上這事匣沼≌玻” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長加叁。 經(jīng)常有香客問我倦沧,道長,這世上最難降的妖魔是什么它匕? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任展融,我火速辦了婚禮,結(jié)果婚禮上豫柬,老公的妹妹穿的比我還像新娘告希。我一直安慰自己,他們只是感情好烧给,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布燕偶。 她就那樣靜靜地躺著,像睡著了一般础嫡。 火紅的嫁衣襯著肌膚如雪指么。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天榴鼎,我揣著相機(jī)與錄音伯诬,去河邊找鬼。 笑死巫财,一個胖子當(dāng)著我的面吹牛姑廉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翁涤,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萌踱!你這毒婦竟也來了葵礼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤并鸵,失蹤者是張志新(化名)和其女友劉穎鸳粉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體园担,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡届谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弯汰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艰山。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖咏闪,靈堂內(nèi)的尸體忽然破棺而出曙搬,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布纵装,位于F島的核電站征讲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橡娄。R本人自食惡果不足惜诗箍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望挽唉。 院中可真熱鬧滤祖,春花似錦、人聲如沸橱夭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棘劣。三九已至俏让,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茬暇,已是汗流浹背首昔。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留糙俗,地道東北人勒奇。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像巧骚,于是被迫代替她去往敵國和親赊颠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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