一、UITabBarController,繼承并封裝UIViewController,原理是每次點(diǎn)擊之后先隱藏上一個(gè)記住的ViewController
UIViewController *viewController = _viewControllers[index];
if (viewController.parentViewController) {
[viewController willMoveToParentViewController:nil];
[viewController.view removeFromSuperview];
[viewController removeFromParentViewController];
}
再insert一個(gè)新的
UIViewController *viewController = _viewControllers[index];
[self addChildViewController:viewController];
viewController.view.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame));
if (self.tabBar) {
[self.view insertSubview:viewController.view belowSubview:self.tabBar];
}
else {
[self.view addSubview:viewController.view];
}
[self didMoveToParentViewController:viewController];
UITabBarController主要用來(lái)管理你提供的content view controllers,而每一個(gè) content view controller則負(fù)責(zé)管理自己的view層級(jí)關(guān)系,通常,當(dāng)你的程序想要提供一些平行(同一個(gè)等級(jí)的)的不同界面,而恰好這些界面使用到的數(shù)據(jù)是一類(lèi)的,或者功能是一個(gè)系列的,那 tab bar interface 是非常有用的. 在這樣的 tab bar interface界面中,你可以設(shè)置許多的 tab ,每一個(gè) tab則一定要指定一個(gè)content view controller,當(dāng)某個(gè)tab被點(diǎn)擊時(shí),UITabBarController就會(huì)選中該tab并且顯示該viewController所持有的content view

觀察上圖,最下面的那個(gè)Tab bar,這是由UITabBarController自己負(fù)責(zé)維護(hù)的,就像UINavigation Bar是由UINavigationController負(fù)責(zé)維護(hù)一樣,不建議被修改,但如果實(shí)在需要改變的話(huà),只能通過(guò)UITabBarController提供的方法去修改。
你有沒(méi)有發(fā)現(xiàn),絕大多數(shù)的iOS程序,如果他用到了UITabBarController,那么他的外觀就像上圖,Tab bar默認(rèn)在下面,但有時(shí)我們又希望將他顯示到最上面去,就像android的聯(lián)系人程序一樣,其實(shí)只要幾句代碼就行了:
self.tabBar.frame = CGRect(x: 0, y: 20, width: UIScreen.main.bounds.size.width, height: 44) ```
下方TabBar條繼承UIView,封裝成UITabBar,UITabBar的高度為49,UITabBarButton在UITabBar中得位置是均分的。


二、一個(gè)標(biāo)準(zhǔn)的 tab bar interface 通常由下列對(duì)象組成:
1.一個(gè) UITabBarController 對(duì)象
2.每一個(gè)tab 都必須有一個(gè)content view controller(所以UITabBarController有一個(gè)屬性是viewControllers)
3.一個(gè)可選的delegate對(duì)象
通常而言,UITabBarController一般作為應(yīng)用程序的rootViewController,而且它不能作為UINavigationController的rootViewController。從xib的Embed in功能也能看出不建議UITabBarController再套一個(gè)UINavigationController,下面是apple官方給的一個(gè)圖片

從這張圖可以看到:最右邊的Assembled views是呈現(xiàn)給用戶(hù)的集成好的界面,它左邊的Window是最底層的窗口,重點(diǎn)來(lái)了,再往左,是Tab bar view,Tab bar view的上方是Navigation view,最后是用戶(hù)定制的視圖。
看完這個(gè),代碼就應(yīng)該很好寫(xiě)了,我們需要把Navigation view加到 Tab bar view的內(nèi)容上去,Tab bar view再加到Window上去。就是Window套UITabBarController,UITabBarController套UINavigationController, UINavigationController套UIViewController。
初始化
let A = AViewController()
let B = BViewController()
let C = CViewController()
let D = DViewController()
let E = EViewController()
let F = FViewController()
let list = [A,B,C,D,E,F]
var vcs = UIViewController
for i in 0 ... 5{
// 每個(gè)VC外套個(gè)Nav 也可不用
vcs.append(UINavigationController(rootViewController: list[i]))
}
A.tabBarItem = UITabBarItem(title: "A", image: UIImage.init(named: "tab_home_n"), selectedImage: UIImage.init(named: "tab_home_s"))
B.tabBarItem = UITabBarItem(title: "B", image: UIImage.init(named: "tab_inspiration_n"), selectedImage: UIImage.init(named: "tab_inspiration_s"))
C.tabBarItem = UITabBarItem(title: "C", image: UIImage.init(named: "tab_me_n"), selectedImage: UIImage.init(named: "tab_me_s"))
D.tabBarItem = UITabBarItem(title: "D", image: UIImage.init(named: "tab_purchase_n"), selectedImage: UIImage.init(named: "tab_purchase_s"))
E.tabBarItem = UITabBarItem(title: "E", image: UIImage.init(named: "tab_search_n"), selectedImage: UIImage.init(named: "tab_search_s"))
F.tabBarItem = UITabBarItem(title: "F", image: UIImage.init(named: "tab_me_n_u"), selectedImage: UIImage.init(named: "tab_me_s_u"))
self.selectedIndex = 2;
C.tabBarItem.badgeValue = "3"
self.viewControllers = vcs
// self.moreNavigationController.navigationBar.isHidden = true
// self.tabBar.frame = CGRect(x: 0, y: 20, width: UIScreen.main.bounds.size.width, height: 44);
其中self繼承自UITabBarController。圖片一般ipad在60*60,iPhone在30*30左右。
三、 再來(lái)看下面這張圖,它描繪了UITabBarController和它的屬性viewControllers、customizableViewControllers和selectedViewController等的關(guān)系

如果你的viewControllers屬性添加了多于五個(gè)的items,那tab bar controller將會(huì)自動(dòng)插入一個(gè)特殊的view controller,稱(chēng)為 More view controller,該 controller 將會(huì)負(fù)責(zé)管理多于的items,這個(gè)More view controller提供一個(gè)自定義的界面,用table的方式呈現(xiàn)多余的view controller,并且view controller的數(shù)量是不限制的。對(duì)于這個(gè)more view controller ,UITabBarController 通過(guò)一個(gè)屬性----moreNavigationController持有它的引用,但看名字就知道他是一個(gè)UINavigationController對(duì)象,所有我們可以修改它的一些屬性,如:
self.tabBar.frame = CGRect(x: 0, y: 20, width: UIScreen.main.bounds.size.width, height: 44); ```
當(dāng)然,如不是必須,最好不要修改它。
在tab bar interface創(chuàng)建好后,我們可以用代碼動(dòng)態(tài)的修改它,如:增加或刪除tab項(xiàng),對(duì)于這種操作,通常我們需要重新指派UITabBarController的viewConrollers屬性來(lái)進(jìn)行,有人可能要問(wèn)了,為什么要重新指派,viewController不是一個(gè)數(shù)組嗎,不能直接通過(guò)數(shù)組的remove方法直接刪除嗎,可別忘了,這個(gè)屬性的類(lèi)型是個(gè)NSArray,不能進(jìn)行刪除,添加的。我們知道,當(dāng)tab bar interface界面顯示后,我們只能在某一時(shí)刻操作一個(gè)界面,因此,修改viewControllers屬性必須在某個(gè)content viewController中完成,我們可以通過(guò)UIViewController的屬性 tabBarController來(lái)獲得UITabBarController的引用,就像獲得UINavigationController的引用一樣:
四、 代理方法
UITabBarController是否能旋轉(zhuǎn)呢?那要看它的那些viewControllers了,如果在viewControllers中只要有一個(gè)viewController不支持某個(gè)方向的旋轉(zhuǎn),那UITabBarControlelr就也不能旋轉(zhuǎn)到該方向
當(dāng)你點(diǎn)擊某個(gè)tab項(xiàng)時(shí),它對(duì)應(yīng)的content viewController會(huì)得到顯示,但有時(shí)也許我們就是不希望某個(gè)被你點(diǎn)擊的view得到顯示,如:某個(gè)viewController所需的數(shù)據(jù)還沒(méi)有完成加載,或者必須等某個(gè)登陸界面 完成登陸后才能激活其他viewController,此時(shí)你可以實(shí)現(xiàn)UITabBarControllerDelgate中的方法
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { }
通過(guò)設(shè)置返回值來(lái)禁止某個(gè)viewController能否被選中。
當(dāng)然你也可以通過(guò)代碼手動(dòng)去選擇某個(gè)viewController,只要設(shè)置UITabBarController的屬性selectedViewController 或者 selectedIndex(從0開(kāi)始),但此時(shí)代理的方法是無(wú)效的,也就是說(shuō),如果你通過(guò)代碼來(lái)選中某個(gè)viewController的話(huà),則肯定是可以選中的。。。
didSelect方法 :當(dāng)你選中某個(gè)tab 項(xiàng)時(shí)調(diào)用,我們可以在這里做一些操作,如隱藏狀態(tài)欄,導(dǎo)航欄什么的
willBeginCustomizingViewControllers:當(dāng)點(diǎn)擊more后出現(xiàn)moreNavigationController畫(huà)面時(shí),點(diǎn)擊那個(gè)edit按鈕時(shí)觸發(fā)
五、UITabBarController還允許你對(duì)viewControllers進(jìn)行排序,你可以使任意一個(gè)viewController出現(xiàn)在第一個(gè)tab項(xiàng)中,上面我們有提到moreNavigationController,當(dāng)tabs超過(guò)5個(gè)時(shí),也就是viewControllers的個(gè)數(shù)超過(guò)5個(gè)時(shí),最后一個(gè)的tab item默認(rèn)為more,然后那些沒(méi)能顯示在tab上的viewController便可通過(guò)moreNavigationController以列表的形勢(shì)顯示,那是不是那些沒(méi)能在tab上顯示的viewController就永遠(yuǎn)只能在moreNavigationController的列表中顯示了??當(dāng)然不是,當(dāng)我么點(diǎn)擊more tab時(shí)會(huì)出現(xiàn)下面圖6的界面,然后再點(diǎn)擊navigationBar左邊的編輯按鈕時(shí)會(huì)出現(xiàn)圖7,此時(shí)你可以把這些顯示的tab直接拉到下面的 tab bar中,從而達(dá)到自定義tab的功能


那如果我希望某個(gè)viewController一直在tab上顯示,二不希望用戶(hù)將其排列到more tab中去,那該怎么辦呢。。。。 UITabBarController有個(gè)屬customizableViewControllers由它來(lái)決定哪些viewController允許重排列。。不過(guò)這里要注意了,默認(rèn)情況下customizableViewControllers 和 viewControllers屬性包含的內(nèi)容是一樣的,你可以手動(dòng)設(shè)置它為viewControllers的字集(只能是字集),但當(dāng)你重新更新了viewControllers時(shí),customizableViewControllers又會(huì)默認(rèn)和viewControllers相等
六、 使用場(chǎng)景
1.作為window的root view controller
2.作為 split view interface(iPad專(zhuān)有界面,不知道的可以百度下)中的其中一個(gè)一個(gè)view controller
3.作為modal view使用
4.作為UIPopoverController(iPad專(zhuān)有)的content view