在StoryBoard中添加NavigationController
在上网看到很多都是用xib添加,使用StoryBard的有两种办法,但我觉得下面用到那种方式比较好,直接在StoryBard中拖入一个NavigationController,在StoryBard中出现两个视图,一个是NavigationController,另一个是TableViewController。
 TableViewController不是必要存在的,只是默认添加上去的,加入需要其他视图,则可以把它删除,重新拖入需要的视图,在NavigationController中按Ctrl键拖到新的视图中,这时弹出的Segue会比平常多了一项,它是属于RelationShip Segue分组的root view controller。
TableViewController不是必要存在的,只是默认添加上去的,加入需要其他视图,则可以把它删除,重新拖入需要的视图,在NavigationController中按Ctrl键拖到新的视图中,这时弹出的Segue会比平常多了一项,它是属于RelationShip Segue分组的root view controller。

使用该Segue后,会发现第二个视图中出现了导航栏。把示意app启动引导的那个箭头拉到第一个视图,也就是NavigationController前面,

启动app会发现,app启动并非引导到NavigationController,而是后来新加的那个视图。在启动后打开的那个页面的导航栏中修改Title属性为"首页",那么往后我们也称这个页面为"首页",再往StoryBoard上面拖一个新的视图,在"首页"中添加一个Button按钮,给Button和新的页面建立Segue,类型选择为push,这个类型与往常用的Modal不一样,使用后原本空白的页面上多了导航栏和工具栏,然后在这个页面的导航栏中修改Title属性为"次页",保存运行一下,当点击Button跳转到次页的时候,发现导航栏多了一个后退的按钮,按钮上的文字也写明是"首页",故名思意就知道点击该按钮就能返回到"首页"了

NavigationItem添加
上面提到的后退按钮,其实是导航栏上面的一种导航栏元素,对于一个导航栏它会有LeftBarItem、RightBarItem、TitleView还有一个比较特殊的位于导航栏左边的BackBarItem。经本人尝试,如果一个导航栏上有BackBarItem和LeftBarItem,那么BackBarItem会被LeftBarItem覆盖,但这个有可能是本人尝试的范围有点窄,涵盖不了所有情况,按本人推断有可能是最后一个加到导航栏的就显示到导航栏上。那下面就演示一下单纯在导航栏上添加NavagationItem。
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(selectLeftAction:)]; self.navigationItem.leftBarButtonItem = leftButton; UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(selectRightAction:)]; self.navigationItem.rightBarButtonItem = rightButton;
在上述代码中添加了左部按钮和右部按钮,两个按钮都被绑定了点击事件,调用不同的方法,如果点击后无操作则传入nil则可。效果如下

两个按钮的图标有所差别,这个在初始化方法的第一个参数所控制,其他值和图片分别如下表所示
 UIBarButtonSystemItemAdd
UIBarButtonSystemItemAdd
 UIBarButtonSystemItemCompose
UIBarButtonSystemItemCompose
 UIBarButtonSystemItemReply
UIBarButtonSystemItemReply
 UIBarButtonSystemItemAction
UIBarButtonSystemItemAction
 UIBarButtonSystemItemOrganize
UIBarButtonSystemItemOrganize
 UIBarButtonSystemItemBookmarks
UIBarButtonSystemItemBookmarks 
 UIBarButtonSystemItemSearch
UIBarButtonSystemItemSearch 
 UIBarButtonSystemItemRefresh
UIBarButtonSystemItemRefresh 
 UIBarButtonSystemItemStop
UIBarButtonSystemItemStop 
 UIBarButtonSystemItemCamera
UIBarButtonSystemItemCamera 
 UIBarButtonSystemItemTrash
UIBarButtonSystemItemTrash 
 UIBarButtonSystemItemPlay
UIBarButtonSystemItemPlay 
 UIBarButtonSystemItemPause
UIBarButtonSystemItemPause 
 UIBarButtonSystemItemRewind
UIBarButtonSystemItemRewind 
 UIBarButtonSystemItemFastForward
UIBarButtonSystemItemFastForward 
 UIBarButtonSystemItemUndo
UIBarButtonSystemItemUndo 
 UIBarButtonSystemItemRedo
UIBarButtonSystemItemRedo 
加入TitleView的代码如下所示
NSArray *array = [NSArray arrayWithObjects:@"元素1",@"元素2", nil]; UISegmentedControl *segmentedController = [[UISegmentedControl alloc] initWithItems:array]; segmentedController.segmentedControlStyle = UISegmentedControlSegmentCenter; [segmentedController addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged]; self.navigationItem.titleView = segmentedController;
这样程序运行起来就有一个分段控件在标题处

因为返回按钮是选择了push类型的Segue而自动生成的,而按钮上的文字都是自动添加上去的,加入要给这个按钮进行修改设置,单纯构造一个UIBarButtonItem赋值到self.navigationItem.backBarButtonItem属性上是不行的。因为这个self.navigationItem.backBarButtonItem并非本页面的返回按钮,实际是以本页面为起始页而导航到的下一页的返回按钮。引用一个网友的说法就是比如在AController跳转到BController,在A设置了self.navigationItem.backBarButtonItem,这个backBarButtonItem为BController的self.navigationController.navigationBar.backItem.backBarButtonItem。那么在要设置这个返回按钮则需要在HGNaviView1Controller中添加以下代码
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"根视图" style:UIBarButtonItemStyleDone target:self action:@selector(On_BackButton_Click)]; [self.navigationItem setBackBarButtonItem:backButton];
效果则如下图

在NavicationController中有两个属性是设置Bar Visibility,一个是设置导航栏的可视性;另一个设置工具栏的可视性。

同样也可以通过代码设置
[self.navigationController setToolbarHidden:false animated:true];
通过上面两种方式设置的结果都是全局的,凡是跟同一个NavigationController建立Segue的视图都会受影响。往工具栏上面添加按钮类似在导航栏上添加按钮,都是使用UIBarButtonItem,但添加到工具栏时是通过一个数组,代码如下所示
UIBarButtonItem *one = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil]; UIBarButtonItem *two = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil]; UIBarButtonItem *three = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil]; UIBarButtonItem *four = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:nil action:nil]; UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; [self setToolbarItems:[NSArray arrayWithObjects:flexItem, one, flexItem, two, flexItem, three, flexItem, four, flexItem, nil]];

当然ToolBar可以自行添加,但如果不把NavigationController统一建立的工具栏隐藏掉的话会导致视图上会有两个工具栏,假如只是个别页面需要显示工具栏的话个人还是觉得把NavigationController统一建立的工具栏隐藏,在需要的界面中自行添加工具栏
[self.navigationController setToolbarHidden:true animated:true]; UIBarButtonItem *one = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil]; UIBarButtonItem *two = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil]; UIBarButtonItem *three = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil]; UIBarButtonItem *four = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:nil action:nil]; UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, self.view.frame.size.height - 44.0, self.view.frame.size.width, 44.0)]; [toolBar setBarStyle:UIBarStyleDefault]; toolBar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; [toolBar setItems:[NSArray arrayWithObjects: flexItem, one, flexItem, two, flexItem, three, flexItem, four, flexItem,nil]]; [self.view addSubview:toolBar];
效果和上图完全一样
TabBarController使用
在使用过NavigationController之后使用TabBarController就容易上手了,在StoryBoard中拖入TabBarController,情况与NavigationController的类似,第一个页面TabBarController并非会呈现到用户界面中去,它只是起到一个管理各个子页面的效果,每个选项卡的具体内容会在他们的视图中编辑,这里默认会建立两个Tab,

如果需要再多的Tab,就可以直接拖入对应的ViewController,在TabBarController页面按Ctrl连接到新页面建立Segue,这里的Segue类型又有不同,Relationship Segue分组中有一个view controllers,就选择那个可以了,这样在TabBarController中会多加了一个Tab。

Tab修改
每个Tab的图标和文字都可以在相应的Tab视图中修改,

图标的尺寸是有限制的,在30*30,如果过大了就会有部分显示不出来,而且就算是给的图标是一个彩色的图片,最终显示在界面上的都只剩下一个轮廓,原图与显示在TabBar中的对比


在代码中同样可以用相应的属性对Tab的标题和图片进行设置
[self.tabBarItem setImage:[UIImage imageNamed:@"SunFlower.gif"]]; [self.tabBarItem setTitle:@"第一选项卡"];
不过有另一个方法setFinishedSelectedImage:withFinishedUnselectedImage则可以把图标完整显示出来,如果图标过大则会占用下面文字的空间,而且图标会按原本的颜色显示出来,图标的显示还会按照选项卡的选中状态来决定
[self.tabBarItem setFinishedSelectedImage:[UIImage imageNamed:@"SunFlower.gif"] withFinishedUnselectedImage:[UIImage imageNamed:@"Ixia.gif"]];
 选中时
选中时
 未选中时
未选中时
在每个TabBarItem中都有一个badgeValue属性,用于设置Tab的小红圈的值,他是NSString,所以可以给他赋的值就不局限在数字,还可是其他字符
self.tabBarItem.badgeValue=@"new";

Tab的数量可以无限地增加,但是在节目是最多可以显示五个Tab标签,如果Tab的数量多于5个的时候,原本第5个的Tab就会变成 ,并且点击进去是一个带TableView的导航页,从第5个开始的Tab会在TableView中显示,从TableView中导航到的Tab页都会带导航栏,以返回TabeView那一页
,并且点击进去是一个带TableView的导航页,从第5个开始的Tab会在TableView中显示,从TableView中导航到的Tab页都会带导航栏,以返回TabeView那一页


导航栏上面还有编辑按钮进入配置Tab的页面

在这一页中可以拖拽各个Tab标签到底部的TabBar中以更改Tab在TabBar中的顺序,而这里显示的Tab是可以通过UITabBarController的customizableViewControllers属性设定的,默认情况下它是和UITabBarController的viewController属性(这个就是UITabBarController拥有Tab的集合)拥有相同的元素,但是也可以通过设置把第6个Tab从customizableViewControllers中去除
NSArray *viewControllers= self.tabBarController.viewControllers; NSMutableArray *newViewControllers=[NSMutableArray arrayWithCapacity:viewControllers.count-1]; for (int i=0; i<[viewControllers count]-1; i++) { [newViewControllers addObject:[viewControllers objectAtIndex:i]]; } self.tabBarController.customizableViewControllers=newViewControllers;
结果第6个Tab就不会出现在Configure页面中了

而对于viewControllers有的Tab而customizableViewControllers没有的Tab,则该部分Tab在编辑状态下不会被移除出TabBar。
关于选中的Tab
通过selectedIndex和selectedViewController都可以获取或设置被选中的Tab,对于设置selectedIndex和selectedViewController而言,仅仅能设置可以选中的Tab,并不能把页面切换过去,而且对于More这个Tab来说还有点特别的情况
UITabBarController的tabBar属性里面也可以通过selectedItem获取选中的UITabBarItem,但是并不能给这个selectedItem赋值,这回引发异常。虽然UITabBar有一些方法是可以改变自身状态,但不能给UITabBarController的tabBar修改自身状态。
UITabBarController的事件
UITabBarController拥有一些事件,通过这些事件可以监测Tab发生变化,这需要给ViewController实现UITabBarControllerDelegate协议,然后设置tabBarController的delegate属性
self.tabBarController.delegate=self;
事件归为两类,一类是单纯tabBar上Tab的选中状态发生变更前后出发的
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController -(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
先触发前者再触发后者,前者有一个布尔类型的返回值,如果返回的是False则会取消Tab的切换,但是通过代码设置SelectedIndex除外。两个参数tabBarController代表着起始的Tab,viewController代表着目标的Tab;
另一类是针对moreViewController的edit操作的
-(void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers -(void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed -(void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
WillBegin…是在进入Edit界面时触发的,WillEnd…和didEnd….是在点击了Done之后相继触发的。