iOS-UIViewController頁面間相互跳轉(zhuǎn)總結(jié)

前言

最近在開發(fā)過程中遇到了一些問題斧吐,是關(guān)于頁面跳轉(zhuǎn)的屋讶,查了網(wǎng)上的相關(guān)資料冰寻,發(fā)現(xiàn)大家說的不是很完整,決定自己總結(jié)一下皿渗。話不多說斩芭,進(jìn)入正題:頁面間跳轉(zhuǎn)/切換的方式主要有以下四種:

1.模態(tài)彈出。

2.UINavigationController的堆棧式Push和Pop乐疆。

3.改變Window的根視圖划乖。

4.改變window。(沒錯(cuò)挤土,window也是可以改變/更換的)

一琴庵、模態(tài)彈出

首先,關(guān)于模態(tài)彈出頁面的跳轉(zhuǎn)方式仰美,我們必須了解清楚presentingViewController和presentedViewController這兩個(gè)屬性迷殿。樓主英文水平有限,僅憑文檔注釋并不能真正理解咖杂。所以親自做了測(cè)試驗(yàn)證(驗(yàn)證過程很簡(jiǎn)單庆寺,在每一個(gè)跳轉(zhuǎn)的頁面打印self.presentingViewController和self.presentedViewController,在此不多贅述)诉字∨吵ⅲ【驗(yàn)證結(jié)果】:presentsViewController?屬性返回父節(jié)點(diǎn)(上一級(jí)頁面)知纷,presentsViewController?屬性返回子節(jié)點(diǎn)(下一級(jí)頁面),如果沒有父節(jié)點(diǎn)或子節(jié)點(diǎn)导披,返回null屈扎。切記:這兩個(gè)屬性返回的是當(dāng)前節(jié)點(diǎn)(當(dāng)前頁面)直接相鄰父子節(jié)點(diǎn)(上下頁面)埃唯,并不是返回最底層(根視圖頁面)或者最頂層(第一相應(yīng)者頁面)的節(jié)點(diǎn)撩匕。(括號(hào)里的注解是樓主更好理解的說法)

1.最基礎(chǔ)的A彈出B(A->B)

[self presentViewController:B? animated:YES completion:nil];//從當(dāng)前界面A到下一個(gè)頁面B

[self dismissViewControllerAnimated:YES completion:nil];//從B頁面模態(tài)返回。

【注】細(xì)心的程序猿發(fā)現(xiàn):在B頁面用self.presentingViewController 調(diào)用dismissViewControllerAnimated:YES completion:nil 也能實(shí)現(xiàn)從B頁面模態(tài)返回墨叛。那么兩者有沒有區(qū)別呢止毕?答案是:沒有區(qū)別。文檔顯示:父節(jié)點(diǎn)負(fù)責(zé)調(diào)用dismiss來關(guān)閉他彈出來的子節(jié)點(diǎn)漠趁,你也可以直接在子節(jié)點(diǎn)中調(diào)用dismiss方法扁凛,UIKit會(huì)通知父節(jié)點(diǎn)去處理。也就是說:[self dismissViewControllerAnimated:YES completion:nil]的實(shí)質(zhì)是通知其父節(jié)點(diǎn)VC調(diào)用 [self dismissViewControllerAnimated:YES completion:nil]闯传;而 [self .presentingViewController dismissViewControllerAnimated:YES completion:nil] 就是直接讓其父節(jié)點(diǎn)VC執(zhí)行撤銷操作谨朝。(有點(diǎn)繞,但是我相信你看的懂)

2.A彈出B甥绿,B再彈出C(A->B->C)

從當(dāng)前界面A到頁面B和從B界面到頁面C代碼是一樣的字币,同樣,從C頁面模態(tài)返回和從B頁面模態(tài)返回代碼也是一樣的共缕。(廢話洗出,但還是要說一下)

如何直接從C返回到A呢?

C返回到A

A彈出B之后图谷,可不可以再用A彈出C呢翩活?


A直接彈出C

【警告內(nèi)容】:“嘗試在A上彈C,但是A已經(jīng)彈了B”便贵。也就是說彈模態(tài)視圖的時(shí)候菠镇,只能用最頂層的的控制器去彈,用底層的控制器去彈會(huì)失敗承璃,并拋出警告利耍。

關(guān)于獲取viewController的最頂層子節(jié)點(diǎn)和最底層父節(jié)點(diǎn),大家可以參考下方的這個(gè)绸硕,寫到我們程序的工具類方法里堂竟。

最頂層子節(jié)點(diǎn)和最底層父節(jié)點(diǎn)

【常見錯(cuò)誤】:在viewDidLoad或者viewWillAppear方法中模態(tài)頁面。

錯(cuò)誤的使用位置
打印警告

上述代碼都會(huì)失敗玻佩,first VC也不會(huì)彈出出嘹,并會(huì)拋出上面的警告。因?yàn)閟elf.view還沒有被添加到視圖樹(父視圖)咬崔,不允許彈出視圖税稼。也就是說烦秩,如果一個(gè)的viewController的視圖還沒被添加到視圖樹(父視圖)上,那么不可以用這個(gè)viewController再區(qū)彈出其他頁面郎仆。

二只祠、UINavigationController的堆棧式Push和Pop

UINavigationController的Push/Pop頁面和《數(shù)據(jù)結(jié)構(gòu)》中的堆棧方式很像,遵守棧的特點(diǎn):先進(jìn)后出扰肌,后進(jìn)先出抛寝。【想象一下】一個(gè)狹長的電梯曙旭,先進(jìn)入的人在里面盗舰,后進(jìn)入的靠近門口,出電梯時(shí)桂躏,靠近門口的(也就是后進(jìn)入電梯的)先出去钻趋,電梯里面的(先進(jìn)入電梯的)后出去。

需要注意的是push和pop是UINavigationController和其子類才有的方法剂习,普通的控制器是沒有的蛮位。 所以,所有的Push和Pop操作(出棧/入棧 )都是依賴于self.navigationController 調(diào)用的鳞绕。

1.最基礎(chǔ)的A Push出B(A->B)

首先失仁,這里實(shí)際指的是NavigationController依次push出AB兩個(gè)頁面。

[self.navigationController pushViewController:B animated:nil];//從當(dāng)前界面A到下一個(gè)頁面B(入棧)

[self.navigationController popViewControllerAnimated:YES];//從B頁面pop返回猾昆。

那么可不可以用self.presentingViewController 來表示要返回的頁面呢陶因。于是猜想并嘗試如下返回方式:

天真的猜想
猜想結(jié)果

由于UINavigationController是一個(gè)視圖控制器的容器,他里面可能放了很多個(gè)控制器垂蜗,而每個(gè)控制器之前并不是父/子節(jié)點(diǎn)的關(guān)系楷扬。所以,[self.navigationController popToViewController:self.presentingViewController animated:YES];的返回方式是錯(cuò)誤的

【驗(yàn)證】:1.在一個(gè)普通的頁面P模態(tài)彈出一個(gè)帶有NavigationController的頁面贴见。2.在一個(gè)帶有NavigationController的頁面模態(tài)一個(gè)普通的頁面P烘苹。

打印父/子節(jié)點(diǎn)

通過打印self.presentingViewController和self.presentedViewController可以發(fā)現(xiàn):頁面P的控制器和UINavigationController是屬同一級(jí)的,其他的均顯示null片部。也就是說我們可以通過判斷self.presentingViewController是否為null來確定當(dāng)前頁面創(chuàng)建之前有沒有進(jìn)行過模態(tài)彈出操作镣衡。

延伸一個(gè)判斷當(dāng)前返回方式的方法:

判斷當(dāng)前頁面的放回方式

2.A push出B,B push出C?

同樣档悠,這里實(shí)際指的是NavigationController依次push出ABC三個(gè)頁面廊鸥。那么想直接從C返回到A怎么實(shí)現(xiàn)呢?

返回到指定頁面

同樣辖所,不可以使用[self.navigationController popToViewController:self.presentingViewController.presentingViewController animated:YES];的方式惰说。

3.返回到根頁面

[self.navigationController popToRootViewController];

4.返回到指定某個(gè)頁面

[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:2] animated:YES];當(dāng)然,也可以使用上面??第二條的方法缘回。

三吆视、改變Window的根視圖

改變window根視圖的方法很簡(jiǎn)單典挑,創(chuàng)建一個(gè)要跳轉(zhuǎn)的頁面或NavigationController,然后用setRootViewController方法設(shè)置即可啦吧。

更換window的根視圖

四您觉、改變Window

在對(duì)接一些已經(jīng)封裝好(封裝度較高)的第三方SDK時(shí)發(fā)現(xiàn):自己程序里已有的NavigationController樣式顏色或者TabBarController樣式與之沖突,而且修改起來相當(dāng)麻煩授滓,這個(gè)時(shí)候建議你直接更換一個(gè)Window琳水,然后所有問題完美解決。(如果你真的碰到過這種情況褒墨,你一定會(huì)感謝我的)

1.更換新的window

更換新的window

2.從新的window頁面返回原來的window

返回原來的window

【特別用法】:如果你想實(shí)現(xiàn)S->A->B->C-...>N,并且在C...N之間的某頁面可以直接回到B炫刷。可以在B頁面模態(tài)一個(gè)帶有NavigationController的頁面郁妈,之后C...N間的頁面跳轉(zhuǎn)用NavigationController的方法,當(dāng)需要直接返回B時(shí)绍申,可以直接調(diào)用模態(tài)返回方法:[self dismissViewControllerAnimated:YES completion:nil];實(shí)現(xiàn)噩咪。(是不是很神奇?????)希望對(duì)你有所幫助极阅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胃碾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子筋搏,更是在濱河造成了極大的恐慌仆百,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奔脐,死亡現(xiàn)場(chǎng)離奇詭異俄周,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)髓迎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門峦朗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人排龄,你說我怎么就攤上這事波势。” “怎么了橄维?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵尺铣,是天一觀的道長。 經(jīng)常有香客問我争舞,道長凛忿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任兑障,我火速辦了婚禮侄非,結(jié)果婚禮上蕉汪,老公的妹妹穿的比我還像新娘。我一直安慰自己逞怨,他們只是感情好者疤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叠赦,像睡著了一般驹马。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上除秀,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天糯累,我揣著相機(jī)與錄音,去河邊找鬼册踩。 笑死泳姐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暂吉。 我是一名探鬼主播胖秒,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼慕的!你這毒婦竟也來了阎肝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤肮街,失蹤者是張志新(化名)和其女友劉穎风题,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫉父,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沛硅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熔号。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稽鞭。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖引镊,靈堂內(nèi)的尸體忽然破棺而出朦蕴,到底是詐尸還是另有隱情,我是刑警寧澤弟头,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布吩抓,位于F島的核電站,受9級(jí)特大地震影響赴恨,放射性物質(zhì)發(fā)生泄漏疹娶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一伦连、第九天 我趴在偏房一處隱蔽的房頂上張望雨饺。 院中可真熱鬧钳垮,春花似錦、人聲如沸额港。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽移斩。三九已至肚医,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間向瓷,已是汗流浹背肠套。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猖任,地道東北人你稚。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像超升,于是被迫代替她去往敵國和親入宦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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