要實(shí)現(xiàn)這種顯示谤碳、隱藏 NavigationBar 的效果,只需要在要隱藏的 Controller 里加入以下代碼
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: true)
}
在要顯示 NavigationBar 的 Controller 里加入以下代碼
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: true)
}
試想一下秤茅,在 mainController 需要隱藏導(dǎo)航欄宙彪,那么就需要在 mainController 的每個(gè)要 push 去的 controller 都需要加入以上代碼。
這就比如一個(gè)公司里,有 java鸿吆、iOS、Android述呐、測(cè)試惩淳、產(chǎn)品、設(shè)計(jì)等不同工種的員工市埋,而團(tuán)隊(duì)的管理者(整個(gè)進(jìn)程)不知道誰(shuí)做 java黎泣、誰(shuí)做測(cè)試、誰(shuí)做設(shè)計(jì)缤谎,需要協(xié)調(diào)時(shí)去當(dāng)面問(wèn)一下:你是什么職位
解決這個(gè)問(wèn)題的方案有兩種:
1抒倚、Coordinator
用一個(gè)或者多個(gè)專(zhuān)門(mén)的Coordinator去負(fù)責(zé)所有的跳轉(zhuǎn)邏輯
我們?cè)趯?xiě)代碼時(shí)經(jīng)常有以下代碼:
navigationController?.pushViewController(AViewController.init(), animated: true)
navigationController?.popViewController(animated: true)
這里省略掉了"self.navigationController"。問(wèn)題在于坷澡,NavigationController 是持有當(dāng)前控制器的托呕,這里的 self.navigationController,就像是你在叫你的領(lǐng)導(dǎo)幫你做事频敛,這里的領(lǐng)導(dǎo)對(duì)你的需求一無(wú)所知项郊。比如工位衛(wèi)生需要打掃,你告訴領(lǐng)導(dǎo)讓他找人打掃斟赚,再比每天都會(huì)有網(wǎng)絡(luò)故障着降,出故障后你告訴領(lǐng)導(dǎo)讓他找人維護(hù)
這顯然是不合理的
Coordinator 就是把 push、pop 等 navigationController 應(yīng)該做的事情拗军,集合起來(lái)處理的一種設(shè)計(jì)模式
Coordinator 負(fù)責(zé)從 AController push 到 BController任洞,從 BController push 到 CCtonroller,再 pop回來(lái)這些事情
push 時(shí) AController 傳參給 Coordinator发侵,Coordinator 再創(chuàng)建 BController 并把參數(shù)給 BController交掏,BController 的回調(diào)交給 Coordinator,Coordinator 去處理回調(diào)而不是 AController 直接處理
好處是解決了領(lǐng)導(dǎo)不認(rèn)識(shí)員工的問(wèn)題刃鳄,不足是仍然要在每個(gè)控制器寫(xiě)上 viewWillAppear 和 setNavigationBarHidden 的代碼
2盅弛、Hook
運(yùn)用 runtime 調(diào)換 controller 的 viewWillAppear 方法,統(tǒng)一處理
這里先講思路再說(shuō)優(yōu)缺點(diǎn)
1叔锐、在 app 啟動(dòng)時(shí)交換 controller 的 viewWillAppear 方法
2挪鹏、新建一個(gè) plist 寫(xiě)入要顯示和要隱藏的控制器名稱(chēng),value 為 bool 控制顯示或者隱藏
3愉烙、交換方法后狰住,就可以判斷是否為 plist 設(shè)置好的 controller,判斷是否執(zhí)行 顯示齿梁、隱藏操作
demo:
https://github.com/haoburongyi/AOPManager
優(yōu)點(diǎn):
無(wú)侵入催植、不用每個(gè) controller 都寫(xiě)一遍 viewWillAppear 和 setNavigationBarHidden 方法肮蛹,精簡(jiǎn)控制器代碼。修改時(shí)只需要修改 plist 文件即可
缺點(diǎn):
沒(méi)有文檔或者沒(méi)有告知下一個(gè)開(kāi)發(fā)者创南,不便于維護(hù)
不足:
無(wú)法到達(dá) Coordinator 的統(tǒng)一 push伦忠、pop 操作
最后談一談為什么我放棄了 Coordinator
我們進(jìn)行 push、pop操作時(shí)稿辙,必須要拿到 controller 才能拿到 navigationController昆码,在 iOS 的子控件 view 中,可以通過(guò)循環(huán)遍歷 superview 拿到 controller邻储,也可以通過(guò)代碼架構(gòu)方式拿到(要確定代碼架構(gòu))赋咽,(比如通過(guò) keyWindow 可以拿到 rootViewController,rootViewController 是 TabbarController吨娜,通過(guò) Child 可 selectedIndex 可以拿到當(dāng)前的 navigationController)進(jìn)行 push
試想一下脓匿,app 內(nèi)有內(nèi)購(gòu)功能,所以 vip 這個(gè) button 就在各個(gè)地方都會(huì)出現(xiàn)宦赠,點(diǎn)擊后沒(méi)開(kāi)通 vip 的用戶(hù)跳轉(zhuǎn)至開(kāi)通頁(yè)面
這里最好的設(shè)計(jì)模式就是 self manager陪毡,就是自己去管理自己,而不是把跳轉(zhuǎn)邏輯交給上層 controller 了勾扭,button 上層嵌套自定義 view毡琉,自定義 view 嵌套 在 tableViewCell 內(nèi),tableViewCell 上層是 tableView妙色,最后才是控制器桅滋,一個(gè) button 往上寫(xiě)回調(diào)已經(jīng)是地獄了,每個(gè)都這么寫(xiě)的就絕望了身辨。不如一句
// self 是view丐谋,為了清晰說(shuō)明這里 “self.” 不省略,controller 為擴(kuò)展的找控制器屬性
self.controller?.navigationController?.pushxxxxxxx
或者
self.navigationController?.pushxxxxxxx
如果在這種時(shí)候繼續(xù)使用 Coordinator栅表,就會(huì)陷入這種地獄笋鄙,解決方法也有师枣,就是在 view 內(nèi)往上一層一層遍歷找到 Coordinator怪瓶,或者用單例的 Coordinator。但是當(dāng) 主頁(yè)践美、新聞洗贰、我的三個(gè)在 tabbarController 上的根 navigationController 用三個(gè)不同的 Coordinator 管理時(shí),找到 Coordinator 也無(wú)法確定調(diào)用哪個(gè)方法陨倡,并且直接違反了使用 Coordinator 的初衷--統(tǒng)一管理
以上為個(gè)人對(duì) navigaitonController 的一些理解敛滋,如有紕漏、錯(cuò)誤或者更好的想法兴革,請(qǐng)指點(diǎn)