iOS中,能用来导航的ViewController主要是UINavigationController
和UITabBarController
两种。很多公司的需求里也有navigation controller和tab bar controller混用的场景。然而对于这两个controller的排列顺序,我一直以来有很大的误解。
以前我认为,排列顺序只可能有一种,就是
UITabBarController
UINavigationController
UIViewController
UINavigationController
UIViewController
以前我们公司做股吧的时候,结构就是这么做的。
这么做本身没有什么问题,可以满足几乎所有的需求。但是我最近遇到的问题就是,UITabBar需要定制(增加一个center button),而且每个tab里面的第二级及以上层级的ViewController都需要隐藏UITabBar。按照网上通行的做法,就是放一个Button到UITabBarController.view上(注意不是UITabBarController.tabBar),然后需要隐藏tabBar的View Controller的init中,加入self.hidesBottomBarWhenPushed=YES
。但是这么一搞的话,每次tabBar隐藏之后再显示,那个加上去的center button都会消失。这也不奇怪,毕竟hack了系统的组件,总会有奇怪的问题。
为了解决这个问题,我观察了一下新浪微博的导航模式。从push动画中可以看出,新浪微博的UITabBarController应该是在UINavigationController下一级的,证据就是push时,tabBar不是向下隐藏,而是向左移出的。所以我试了一下如下的结构:
UINavigationController
UITabBarController
UIViewController
UIViewController
UIViewController
发现其实这样也是可以的。在UIViewController里,self.navigationController
也是有值的,说明这个UINavigationController
不仅传到了UITabBarController.navigationController
,还传到了下面一级。
不过这样一来,对NavigationItem的定制会出现问题,也就是UITabBarController
在切换的时候,不会自动将自己的NavigationItem适配成当前被选中的ViewController的NavigationItem。所以在ViewController中,设置self.navigationItem.title
这样的语句是不起作用的。
我现在想到的一个workaround是,在UIViewController中的viewWillAppear
函数里,把self.navigationItem
的值复制到self.tabBarController.navigationItem
中。不知道有没有更好的办法。
单NavigationController有很多好处,最显著的就是导航逻辑变得简单了。不需要判断现在到底切在哪个tab下的Navigation中。
不过呢,这种结构应该在东财的应用里是不适用的。因为它的基础是UITabBar只在最开始出现,第二层级以上的界面都没有tabBar。而东财系列的应用一直以来有非常复杂的tabBar显示逻辑需求,可能自定义tabBar是唯一的选择了。