iOS導(dǎo)航欄之UINavigationController,UINavigationbar和UINavigationItem的關(guān)系

前言

本文主要從UINavigationController,UINavigationBar和UINavigationItem的概念入手钳吟,通過介紹這三者之間的關(guān)系,來學(xué)會(huì)導(dǎo)航控制器的使用贴见。

學(xué)習(xí)新知識分為兩個(gè)狀態(tài):學(xué)會(huì)如何運(yùn)用和理解知識的原理烘苹,自如運(yùn)用。本篇主要側(cè)重于后者片部。

self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationItem.title = @"我是標(biāo)題";

通常镣衡,我們都是這樣設(shè)置導(dǎo)航欄的樣式。但是為什么標(biāo)題需要使用視圖控制器的navigationItem對象中設(shè)置,而導(dǎo)航欄的背景色卻是在導(dǎo)航控制器navigationBar對象中設(shè)置廊鸥?

接下來我們看一下蘋果文檔中對三者的解釋:

一望浩、UINavigationController

UINavigationController是一種可以管理層級內(nèi)容的導(dǎo)航控制器,也就是我們常說的容器控制器惰说。它通過一個(gè)棧對象實(shí)現(xiàn)了不同ViewController之間的跳轉(zhuǎn)和返回操作磨德。棧底的viewcontroller稱為rootViewController, 棧頂?shù)膶ο缶褪钱?dāng)前顯示在屏幕上的ViewController.

官方文檔

A navigation controller object manages the currently displayed screens using the navigation stack, which is represented by an array of view controllers. The first view controller in the array is the root view controller. The last view controller in the array is the view controller currently being displayed. You add and remove view controllers from the stack using segues or using the methods of this class. The user can also remove the topmost view controller using the back button in the navigation bar or using a left-edge swipe gesture.

二、UINavigationBar

UINavigationBar是顯示在屏幕最上方的一條bar吆视,包含了當(dāng)前view上的一些導(dǎo)航按鈕典挑,主要有左側(cè)的返回按鈕,居中的標(biāo)題欄和可選的右側(cè)按鈕啦吧∧酰可以單獨(dú)使用也可以和UINavigationController結(jié)合在一起使用。

UINavigationController負(fù)責(zé)控制顯示在界面頂部的UINavigationBar和一個(gè)可選的顯示在界面底部的toolbar丰滑。UINavigationBar默認(rèn)顯示顾犹,UINavigationController負(fù)責(zé)在頁面跳轉(zhuǎn)時(shí)使用當(dāng)前棧頂viewController的內(nèi)容更新UINavigationBar.

官方文檔

A UINavigationBar object is a bar, typically displayed at the top of the window, containing buttons for navigating within a hierarchy of screens. The primary components are a left (back) button, a center title, and an optional right button. You can use a navigation bar as a standalone object or in conjunction with a navigation controller object.

The navigation controller manages the navigation bar at the top of the interface and an optional toolbar at the bottom of the interface. The navigation bar is always present and is managed by the navigation controller itself, which updates the navigation bar using the content provided by the view controllers on the navigation stack.

三倒庵、UINavigationItem

UINavigationItem對象負(fù)責(zé)管理顯示在UINavigationBar中的按鈕和視圖褒墨。當(dāng)創(chuàng)建一個(gè)UINavigationController界面時(shí),每一個(gè)進(jìn)棧的viewController都必須有一個(gè)UINavigationItem對象擎宝;UINavigationItem對象中包含了要顯示在導(dǎo)航欄上的按鈕或者視圖郁妈。導(dǎo)航控制器使用最上層的兩個(gè)viewcontroller中的navigationItem中的內(nèi)容來展示當(dāng)前的導(dǎo)航欄。

官方文檔

A UINavigationItem object manages the buttons and views to be displayed in a UINavigationBar object. When building a navigation interface, each view controller pushed onto the navigation stack must have a UINavigationItem object that contains the buttons and views it wants displayed in the navigation bar. The managing UINavigationController object uses the navigation items of the topmost two view controllers to populate the navigation bar with content.

蘋果的UINavigationBar官方文檔中有一段對三者的關(guān)系的描述非常關(guān)鍵:

當(dāng)視圖控制器在導(dǎo)航過程中绍申,導(dǎo)航控制利用視圖控制器提供的navigationItem的屬性作為導(dǎo)航控制器的導(dǎo)航欄的model對象噩咪。navigationItem默認(rèn)使用視圖控制器的title屬性,但是我們也可以通過自定義navigationItem的屬性達(dá)到完全控制導(dǎo)航欄內(nèi)容的效果。

A navigation controller uses the navigationItem property on UIViewController to provide the model objects to its navigation bar when navigating a stack of view controllers. The default navigation item uses the view controller’s title, but you can override the navigationItem on a UIViewController subclass to gain complete control of the navigation bar’s content.

四、三者的關(guān)系:

  1. 每一個(gè)導(dǎo)航控制器都會(huì)自動(dòng)生成一個(gè)與之對應(yīng)的導(dǎo)航欄(UINavigationBar)對象瓶珊;
  2. 當(dāng)一個(gè)新的ViewController加入到導(dǎo)航控制器時(shí)管削,導(dǎo)航欄使用ViewController提供的navigationItem對象作為導(dǎo)航欄的model對象來渲染導(dǎo)航欄;
  3. 導(dǎo)航欄會(huì)保存導(dǎo)航控制器棧內(nèi)最上層的兩個(gè)ViewController的navigationItem對象;
  4. ViewController從導(dǎo)航控制器棧移除時(shí)慌闭,navigationItem會(huì)同時(shí)從navigationBar的視圖棧內(nèi)移除。

五、實(shí)踐

理清楚三者之間的關(guān)系后, 實(shí)現(xiàn)一個(gè)指定效果的導(dǎo)航欄就變得非常簡單:

  1. 生成導(dǎo)航控制器俄周,并指定rootViewController;

ViewController *viewController = [[ViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navigationController;
  1. 通過navigationBar設(shè)置導(dǎo)航欄的外觀,包括顏色和tintColor;
self.navigationController.navigationBar.backgroundColor = [UIColor orangeColor];
self.navigationController.navigationBar.tintColor = [UIColor grayColor];

  1. 新建一個(gè)ViewController,通過設(shè)置其navigationItem來實(shí)現(xiàn)指定的效果髓迎;
self.navigationItem.title = @"首頁";

P.S. 總之峦朗,如果需要改變navigationBar的外觀,就在navigationBar對象上做文章排龄,如果需要在導(dǎo)航欄上顯示按鈕或者視圖波势,就在navigationItem屬性上做文章。

六、深入驗(yàn)證理論(不感興趣的可以跳過不看)

這個(gè)部分主要通過調(diào)試手段驗(yàn)證第四部分的理論尺铣,有興趣的可以動(dòng)手驗(yàn)證一下闭翩,對您的學(xué)習(xí)大有裨益。
在你的項(xiàng)目中迄埃,準(zhǔn)備三個(gè)ViewController, 分別設(shè)置其導(dǎo)航欄標(biāo)題和背景色疗韵,跳轉(zhuǎn)順序?yàn)锳 -> B -> C,并分別在三個(gè)頁面的viewDidAppear代理方法中打上斷點(diǎn)侄非,運(yùn)行程序蕉汪。

驗(yàn)證一:程序停留在A頁面,使用lldb打印navigationBar對象

po self.navigationController.navigationBar //UINavigationBar: 0x7f8b1b508e50; 

繼續(xù)執(zhí)行逞怨,并點(diǎn)擊按鈕者疤,從A頁面跳轉(zhuǎn)到B頁面,程序會(huì)停留在B頁面叠赦,同樣打印navigationBar

po self.navigationController.navigationBar //UINavigationBar: 0x7f8b1b508e50; 

由此可見驹马,無論在哪個(gè)頁面,使用的都是同一個(gè)navigationBar對象除秀;

驗(yàn)證二糯累、有視圖控制器進(jìn)棧時(shí),導(dǎo)航欄使用視圖控制器的navigationItem對象作為model對象册踩。

保留斷點(diǎn)泳姐,重新運(yùn)行項(xiàng)目,讓斷點(diǎn)停留在A頁面暂吉,使用lldb打印navigationItem和navigationBar


po self.navigationItem //<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'>
po self.navigationController.navigationBar.subviews 

//
//<__NSArrayM 0x600000055870>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1b614930; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000234200>>: item=<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'> title=頁面A>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
//)
//

由此可知胖秒,當(dāng)新的ViewController入棧時(shí),navigationBar會(huì)使用ViewController提供的navigationItem對象慕的。

驗(yàn)證三阎肝、navigationBar只保留最上層的2個(gè)viewController的navigationItem.

在頁面B和C分別打印navigaitonBar, 得到的結(jié)果如下:


po self.navigationController.navigationBar.subviews 
//__NSArrayM 0x608000053da0>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1d00f9d0; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000234200>>: item=<<UINavigationItem: 0x6000001c8e80>: title:'頁面B'> title=頁面B>,
//<<UINavigationItemButtonView: 0x7f8b1b614930; frame = (8 6; 54 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000036520>>: item=<<UINavigationItem: 0x6180001c8ac0>: title:'頁面A'> title=頁面A>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
)

 po self.navigationController.navigationBar.subviews
//<__NSArrayM 0x618000053fe0>(
//<_UIBarBackground: 0x7f8b1b509310; frame = (0 -20; 375 64); userInteractionEnabled = NO; layer = <CALayer: 0x618000032a00>>,
//<<UINavigationItemView: 0x7f8b1d00fdc0; frame = (144 8; 87 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000236120>>: item=<<UINavigationItem: 0x6000001c9240>: title:'頁面C'> title=頁面C>,
//<<UINavigationItemButtonView: 0x7f8b1b617410; frame = (8 6; 106 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000373a0>>: item=<<UINavigationItem: 0x6000001c8e80>: title:'頁面B'> title=頁面B>,
//<_UINavigationBarBackIndicatorView: 0x7f8b1b6095d0; frame = (8 11.5; 13 21); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080000338e0>>
)

由此可見,navigationBar確實(shí)只保存了最上層的2個(gè)viewController的navigationItem.

驗(yàn)證四肮街、ViewController從導(dǎo)航控制器移除后风题,navigationItem也會(huì)從navigationBar中被移除。

這個(gè)大家自行驗(yàn)證一下低散。

能堅(jiān)持讀到這里的同學(xué)俯邓,都非常有耐心的??

七、練習(xí)部分

既然已經(jīng)花費(fèi)了這么多精力熔号,那就趁熱打鐵稽鞭,練習(xí)一下。

  1. 實(shí)現(xiàn)微信我的-朋友圈頁面的導(dǎo)航效果引镊;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末朦蕴,一起剝皮案震驚了整個(gè)濱河市篮条,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吩抓,老刑警劉巖涉茧,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異疹娶,居然都是意外死亡伴栓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門雨饺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钳垮,“玉大人,你說我怎么就攤上這事额港〗攘” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵移斩,是天一觀的道長肚医。 經(jīng)常有香客問我,道長向瓷,這世上最難降的妖魔是什么肠套? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮风罩,結(jié)果婚禮上糠排,老公的妹妹穿的比我還像新娘舵稠。我一直安慰自己超升,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布哺徊。 她就那樣靜靜地躺著室琢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪落追。 梳的紋絲不亂的頭發(fā)上盈滴,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音轿钠,去河邊找鬼巢钓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疗垛,可吹牛的內(nèi)容都是我干的症汹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼贷腕,長吁一口氣:“原來是場噩夢啊……” “哼背镇!你這毒婦竟也來了咬展?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瞒斩,失蹤者是張志新(化名)和其女友劉穎破婆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胸囱,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祷舀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烹笔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔑鹦。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖箕宙,靈堂內(nèi)的尸體忽然破棺而出嚎朽,到底是詐尸還是另有隱情,我是刑警寧澤柬帕,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布哟忍,位于F島的核電站,受9級特大地震影響陷寝,放射性物質(zhì)發(fā)生泄漏锅很。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一凤跑、第九天 我趴在偏房一處隱蔽的房頂上張望爆安。 院中可真熱鬧,春花似錦仔引、人聲如沸扔仓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翘簇。三九已至,卻和暖如春儿倒,著一層夾襖步出監(jiān)牢的瞬間版保,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工夫否, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彻犁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓凰慈,卻偏偏與公主長得像汞幢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子溉瓶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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