ViewController編程指南展示和過渡-呈現視圖控制器

有兩種方法在屏幕上顯示視圖控制器:將其嵌入到容器視圖控制器中或呈現它。 容器視圖控制器提供應用程序的主導航,但是呈現視圖控制器也是一個重要的導航工具。 您使用直接演示在當前視圖控制器的頂部顯示新的視圖控制器。 通常,當您想要實現模態界面時,您可以使用呈現視圖控制器,但是您也可以將它們用于其他用途。

支持呈現視圖控制器內置在UIViewController類中,并且可用于所有視圖控制器對象。 您可以呈現來自任何其他視圖控制器的任何視圖控制器,雖然UIKit可能會將請求重新路由到不同的視圖控制器。 呈現視圖控制器創建被稱為呈現視圖控制器的原始視圖控制器和被顯示的新視圖控制器之間的關系,被稱為呈現的視圖控制器。 此關系形成視圖控制器層次結構的一部分,并且保持就位,直到呈現的視圖控制器被解除。

展示與過渡過程

呈現視圖控制器是一種快速和簡單的方式來將新內容設置到屏幕上。 UIKit中內置的演示機制允許您使用內置或自定義動畫顯示新的視圖控制器。 內置的展示和動畫需要很少的代碼,因為UIKit處理所有的工作。 您也可以創建自定義展示和動畫,而不需要額外的工作,并與任何視圖控制器使用它們。

您可以以編程方式或使用segues啟動視圖控制器的呈現。 如果你在設計時知道你的應用程序的導航,segues是最簡單的方式來啟動界面。 對于更多動態界面,或在沒有專門控制來啟動segue的情況下,使用UIViewController的方法來呈現視圖控制器。

呈現方式

視圖控制器的呈現方式控制其在屏幕上的外觀。 UIKit定義了許多標準的呈現方式,每個都有一個特定的外觀和意圖。 您還可以定義自己的自定義呈現方式。 在設計應用程序時,選擇最適合您想要做的操作的呈現方式,并將適當的時候分配給要呈現的視圖控制器的modalPresentationStyle屬性。

全屏呈現方式

全屏呈現方式覆蓋整個屏幕,防止與底層內容的交互。 在水平常規環境中,只有一個全屏方式完全覆蓋基礎內容。 其余包含調光視圖或透明度,以允許下層視圖控制器的部分顯示。 在水平緊湊的環境中,全屏演示自動適應UIModalPresentationFullScreen方式并涵蓋所有底層內容。

圖8-1說明使用uimodalpresentationfullscreen,uimodalpresentationpagesheet呈現方式的外觀,并在水平正常的環境uimodalpresentationformsheet風格。在圖中,頂部左側的綠色視圖控制器呈現頂部右側的藍色視圖控制器,每個顯示樣式的結果如下所示。對于一些呈現方式,UIKit插入一個調光的視圖的兩個視圖控制器的內容。

圖8-1全屏呈現方式

VCPG_PresentationStyles _fig_8-1_2x.png

注意

當使用UIModalPresentationFullScreen方式呈現視圖控制器時,UIKit通常在
轉換動畫完成后刪除基礎視圖控制器的視圖。 您可以通過指定
UIModalPresentationOverFullScreen樣式來防止刪除這些視圖。 當呈現的視
圖控制器具有允許基礎內容顯示的透明區域時,您可以使用該樣式。

當使用全屏呈現方式之一時,發起呈現的視圖控制器必須自己覆蓋整個屏幕。 如果呈現視圖控制器不覆蓋屏幕,UIKit會在視圖控制器層次結構上查找覆蓋全屏的,直到它找到一個。 如果它找不到填充屏幕的中間視圖控制器,UIKit使用窗口的根視圖控制器。

彈出方式

UIModalPresentationPopover方式在彈出視圖中顯示視圖控制器。 彈出式窗口可用于顯示附加信息或與關注或選定對象相關的項目列表。 在水平常規環境中,彈出視圖僅覆蓋屏幕的一部分,如圖8-2所示。 在水平緊湊的環境中,默認情況下,popovers適應UIModalPresentationOverFullScreen表示方式。 在popover視圖之外輕擊會自動關閉popover。

圖8-2 彈出呈現方式

VCPG_popover-style_2x.png

因為彈出方式適合在水平緊湊的環境中的全屏顯示,所以通常需要修改彈出方式代碼來處理適配。 在全屏模式下,您需要一種方法來關閉所顯示的popover。 你可以通過添加一個按鈕,將popover嵌入一個可忽略的容器視圖控制器,或者改變自適應行為本身。

當前上下文方式

UIModalPresentationCurrentContext樣式涵蓋了接口中的特定視圖控制器。 當使用上下文方式時,通過將其definitionsPresentationContext屬性設置為YES來指定要覆蓋哪個視圖控制器。 圖8-3示出了僅覆蓋拆分視圖控制器的一個子視圖控制器的當前上下文表示。

圖8-3 當前上下文呈現方式

VCPG_CurrentContextStyles_2x.png

注意

當使用UIModalPresentationFullScreen方式呈現視圖控制器時,UIKit通常在
轉換動畫完成后刪除基礎視圖控制器的視圖。 您可以通過指定
UIModalPresentationOverCurrentContext樣式來防止刪除這些視圖。 當呈現
的視圖控制器具有允許基礎內容顯示的透明區域時,您可以使用該方式。

定義呈現上下文的視圖控制器還可以定義在呈現期間使用的轉換動畫。 通常,UIKit使用呈現的視圖控制器的modalTransitionStyle屬性中的值在屏幕上動畫顯示控制器。 如果演示文稿上下文視圖控制器的providesPresentationContextTransitionStyle設置為YES,UIKit將使用該視圖控制器的modalTransitionStyle屬性中的值。

當轉換到水平緊湊環境時,當前上下文樣式適應UIModalPresentationFullScreen樣式。 要更改此行為,請使用自適應呈現委派來指定不同的呈現樣式或視圖控制器。

自定義呈現方式

UIModalPresentationCustom方式允許你使用定義的自定義方式來呈現視圖控制器。 創建自定義方式涉及對UIPresentationController子類化,并使用其方法將任何自定義視圖動畫化到屏幕上,并設置呈現的視圖控制器的大小和位置。 呈現控制器還處理由于呈現的視圖控制器的特性的改變而發生的任何適配。

過渡方式

過渡方式確定用于顯示所呈現的視圖控制器的動畫類型。 對于內置的轉換方式,可以將一個標準轉換方式分配給要顯示的視圖控制器的modalTransitionStyle屬性。 當您呈現視圖控制器時,UIKit將創建與該樣式對應的動畫。 例如,圖8-4說明了標準上滑過渡(UIModalTransitionStyleCoverVertical)如何在屏幕上動畫視圖控制器。 視圖控制器B從屏幕開始并且向上和向上移動視圖控制器A的頂部。當視圖控制器B被關閉時,動畫反轉,使得B向下滑動以顯示A.

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

VCPG_SlideTransition_fig_8-1_2x.png

您可以使用animator對象和轉換委托創建自定義轉場。 動畫制作器對象創建用于將視圖控制器放置在屏幕上的過渡動畫。 轉換委托在適當的時間將動畫對象提供給UIKit。

呈現或顯示視圖控制器

UIViewController類提供了兩種顯示視圖控制器的方法:

  • showViewController:sender:和showDetailViewController:sender:方法提供了最適應和靈活的方式來顯示視圖控制器。 這些方法讓呈現視圖控制器決定如何最好地處理呈現。 例如,容器視圖控制器可以將視圖控制器合并為子控制器,而不是模態地呈現它。 默認行為以模態方式呈現視圖控制器。
  • presentViewController:animated:completion:方法總是以模態方式顯示視圖控制器。 調用此方法的視圖控制器可能不會最終處理呈現,但呈現總是模態。 此方法適應水平緊湊環境的呈現風格。

showViewController:sender:和showDetailViewController:sender:方法是啟動呈現視圖的首選方法。 視圖控制器可以在不知道關于視圖控制器層次結構的其余部分或當前視圖控制器在該層次結構中的位置的任何情況下調用它們。 這些方法還使得更容易在應用程序的不同部分重用視圖控制器,而無需編寫條件代碼路徑。

呈現視圖控制器

有幾種方式來啟動視圖控制器的呈現:

  • 使用segue自動呈現視圖控制器。 segue使用您在Interface Builder中指定的信息實例化并呈現視圖控制器。
  • 使用showViewController:sender:或showDetailViewController:sender:方法來顯示視圖控制器。 在自定義視圖控制器中,您可以將這些方法的行為更改為更適合于視圖控制器的行為。
  • 調用presentViewController:animated:completion:方法以模態方式呈現視圖控制器。

顯示視圖控制器

當使用showViewController:sender:和showDetailViewController:sender:方法時,在屏幕上獲取新的視圖控制器的過程是直接的:

  1. 創建要顯示的視圖控制器對象。 在創建視圖控制器時,您有責任使用執行其任務所需的任何數據對其進行初始化。
  2. 將新視圖控制器的modalPresentationStyle屬性設置為首選顯示方式。 此方式可能不會在最終呈現中使用。
  3. 將視圖控制器的modalTransitionStyle屬性設置為所需的過渡動畫方式。 此方式可能不會在最終的動畫中使用。
  4. 調用當前視圖控制器的showViewController:sender:和showDetailViewController:sender:方法。

UIKit將對showViewController:sender:和showDetailViewController:sender:方法的調用轉發到相應的呈現視圖控制器。 然后,視圖控制器可以決定如何最好地執行呈現,并且可以根據需要改變呈現和轉換樣式。 例如,導航控制器可以將視圖控制器推到其導航堆棧上。

模式地呈現視圖控制器

當直接呈現視圖控制器時,您可以告訴UIKit如何顯示新的視圖控制器以及如何在屏幕上動畫。

  • 創建要顯示的視圖控制器對象。
    在創建視圖控制器時,您有責任使用執行其任務所需的任何數據對其進行初始化。
  • 將新視圖控制器的modalPresentationStyle屬性設置為所需的顯示樣式。
  • 將視圖控制器的modalTransitionStyle屬性設置為所需的動畫樣式。
  • 調用當前視圖控制器的presentViewController:animated:completion:方法。

調用presentViewController:animated:completion:方法的視圖控制器可能不是實際執行模態呈現的視圖控制器。 呈現風格確定如何呈現視圖控制器,包括呈現視圖控制器所需的特性。 例如,全屏顯示必須由全屏視圖控制器啟動。 如果當前呈現視圖控制器不合適,UIKit會遍歷視圖控制器層次結構,直到它找到一個。 完成模態顯示后,UIKit將更新受影響的視圖控制器的presentingViewController和presentedViewController屬性。

清單8-1演示了如何以編程方式呈現視圖控制器。 當用戶添加新配方時,應用程序通過呈現導航控制器來提示用戶關于配方的基本信息。 選擇了一個導航控制器,以便有一個標準的地方放置取消和完成按鈕。 使用導航控制器還使得將來更容易擴展新的配方界面。 所有你需要做的是在導航堆棧上推新的視圖控制器。

清單8-1以編程方式呈現視圖控制器

- (void)add:(id)sender {
   // Create the root view controller for the navigation controller
   // The new view controller configures a Cancel and Done button for the
   // navigation bar.
   RecipeAddViewController *addController = [[RecipeAddViewController alloc] init];
 
   addController.modalPresentationStyle = UIModalPresentationFullScreen;
   addController.transitionStyle = UIModalTransitionStyleCoverVertical;
   [self presentViewController:addController animated:YES completion: nil];
}

在彈出中呈現視圖控制器

彈出需要額外配置才能顯示它們。 將模態表示樣式設置為UIModalPresentationPopover后,請配置以下與彈出相關的屬性:

  • 將視圖控制器的preferredContentSize屬性設置為所需的大小。
  • 使用關聯的UIPopoverPresentationController對象設置彈出錨點,該對象可以從視圖控制器的popoverPresentationController屬性訪問。 僅設置以下選項之一:
    * 將barButtonItem屬性設置為bar按鈕項。
    * 將sourceView和sourceRect屬性設置為其中一個視圖中的特定區域。

您可以使用UIPopoverPresentationController對象根據需要對彈出的外觀進行其他調整。 彈出呈現控制器還支持一個委托對象,您可以使用它來響應演示過程中的更改。 例如,您可以使用代理在彈出窗口出現,消失或在屏幕上重新定位時進行響應。

取消呈現的視圖控制器

要關閉提交的視圖控制器,請調用呈現視圖控制器的dismissViewControllerAnimated:completion:方法。 您還可以在呈現的視圖控制器本身上調用此方法。 當您在提供的視圖控制器上調用該方法時,UIKit自動將請求轉發到呈現視圖控制器。

在關閉視圖控制器之前,始終從視圖控制器保存任何重要信息。 取消視圖控制器會從視圖控制器層次結構中刪除它,并從屏幕中刪除它的視圖。 如果您沒有強烈引用存儲在其他位置的視圖控制器,則關閉它會釋放與其關聯的內存。

如果呈現的視圖控制器必須將數據返回給呈現視圖控制器,則使用委托設計模式來促進傳送。 委托使得在應用程序的不同部分中重用視圖控制器更加容易。 使用委托,所呈現的視圖控制器存儲對實現來自形式協議的方法的委托對象的引用。 當它收集結果時,呈現的視圖控制器在其委托上調用這些方法。 在典型的實現中,呈現視圖控制器使其自身成為其呈現的視圖控制器的委托。

雖然可以在同一故事板中的視圖控制器之間創建段,但是不能在故事板之間創建段。 當要顯示存儲在不同故事板中的視圖控制器時,必須在顯示之前顯式地實例化該視圖控制器,如清單8-2所示。 該示例以模態呈現視圖控制器,但您可以將其推送到導航控制器或以其他方式顯示它。

清單8-2從故事板加載視圖控制器

UIStoryboard* sb = [UIStoryboard storyboardWithName:@"SecondStoryboard" bundle:nil];
MyViewController* myVC = [sb instantiateViewControllerWithIdentifier:@"MyViewController"];
 
// Configure the view controller.
 
// Display the view controller
[self presentViewController:myVC animated:YES completion:nil];

沒有要求你在應用程序中創建多個故事板。 這里,雖然,在少數情況下,多個故事板可能是有用的:

  • 你有一個大型編程團隊,用戶界面的不同部分分配給團隊的不同部分。 每個團隊在不同的故事板文件中擁有其用戶界面的部分,以最小化爭用。
  • 你購買或創建了預定義視圖控制器類型集合的庫; 那些視圖控制器的內容在由庫提供的故事板中定義。
  • 您的內容需要顯示在外部屏幕上。 在這種情況下,您可以將與備用屏幕關聯的所有視圖控制器保留在單獨的故事板中。 同一場景的另一種模式是編寫自定義segue。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容