实现:仿新浪微博
1、项目配置
1> 取消横竖屏
2> 设置图标和启动图片
3> 删除MainStoryboard,全部代码创建
2、添加TabBarController
2.1 创建窗口
1>在didFinishLaunchingWithOptions方法中,创建窗口,设置根控制器,显示窗口
2> 添加TabBarController的子控制器
3>抽取重复代码
注:上述方法限制每次创建的都是UIViewController,实际使用中,需要设置不同的控制器作为TabBarController的子控制器
4> 改进
添加HWHomeViewController等控制器,在创建后传递给上述设置方法,设置Item和图片
2.2 自定义HWTabBarViewController
注:上述创建的四个控制器应该属于TabBarController,由TabBarController去管理,而且HWAppDelegate代理的功能主要是创建窗口,设置根控制器TabBarController,不需要管TabBarController里面的具体实现,因此上述代码不应该放在HWAppDelegate方法中,应该单独抽取出来,在HWTabBarViewController的viewDidLoad方法中实现添加子控制器
3、添加NavigationController
3.1 项目结构
3.2 包装导航控制器
3.3 导航控制器跳转
1> HWMessageCenterViewController假数据
2> 点击Cell跳转
4、自定义导航控制器
4.1 设置导航控制器leftBarButtonItem和rightBarButtonItem
箭头:返回上一个控制器
三点:返回导航控制器的根控制器
1> 基本实现
注:对于自定义UIButton(或者其他UI控件),必须设置其尺寸,否则可能不会显示!!!
注:UIView写分类
注:当需要修改控件的尺寸的时,往往需要先取出frame,再修改frame,最后再设置frame,比较麻烦,可以写一个UIView的分类,封装修改尺寸的方法!
重写上面上述属性的setter/getter方法,设置/取出控件frame,再将头文件写到pch文件中,其他类可以直接调用
2>其他控制器跳转时也实现上述要求
若其他控制器跳转时,也需要实现设置导航控制器为同样的Item,则直接将上述代码复制到每个控制器的viewDidLoad方法中即可。
但是,若控制器很多,则上述重复代码复制太多,应该抽取出来。
方法一:考虑继承
但是对于控制器来说,一般不使用继承,因为控制器种类很多,不可能将所有控制器继承自同一个控制器,通过一个控制器来实现统一。
比如:导航控制器中既有UIViewController,又有UITableViewController,且需要同时设置导航控制器的Item,则不能通过继承同一个控制器,设置其Item来实现。
方案二:自定义导航控制器
重写push方法,就可以得到传进来的控制器参数
4.2 自定义导航控制器
1> 在3.2节中,包装导航控制器添加到HWTabBrViewController中时,包装的导航控制器为自定义导航控制器
2>重写自定义导航控制器的push方法!!!
注1:此时每个控制器的导航栏都显示同样的Item!
注2:若某个特定的控制器,其导航栏需要显示另一个Item(或者清空),则可以在其viewDidLoad方法中直接设置即可,会覆盖自定义导航控制器中的操作!
注3:将隐藏TabBar的操作也封装到自定义导航控制器的push方法中,但是需要放在调用父类的push方法之前,否则不会隐藏!
5、项目文件分类
Home(首页)、MessageCenter(消息)、Discover(发现)、Profile(我):四个文件夹存放不同功能模块,里面分别以MVC结构划分
Main(主要):存放公共模块,包含MVC结构(主框架)、Category(分类)、Lib(第三方框架)、Other(HWAppDelegate、main.m)
Temp(临时):存放临时文件,如用于测试的控制器
6、封装UIBarButtonItem的创建
6.1 Item创建分析
之前对设置导航栏Item内容,封装到自定义导航控制器的push方法中,但是每个根控制器的导航栏内容,仍然需要设置其Item内容。
方法:在根控制器(如HWHomeViewController)的viewDidLoad方法中设置。
注:带来问题,每个根控制器都需要这样设置左右的Item,而且代码跟导航控制器的push方法中设置Item的代码重复
6.2 初步封装
将HWHomeViewController中的Item创建方法抽取出来,但是这样只能保证在HWHomeViewController中能够快速创建,在其他控制器中仍然需要重复代码创建。
6.3 创建UIBarButtonItem分类
注意:一定要添加target参数,用于表示哪个对象,如果直接将上面的代码复制过来是self,会导致点击Item的时候调用分类的action方法(属于控制器,不属于Item),程序崩溃!!!并将头文件放到pch文件中。则在需要创建Item的时候,直接调用分类的方法即可!!!
如:
7、小结
8、设置导航栏主题
注:消息控制器中设置导航栏右边Item(写私信)不使能,若将enable = NO放到viewDidLoad方法中,主体来不及渲染,会没有显示灰色,应该放在viewWillAppear方法中
注1:造成上述问题的主要原因是:由于View采用的是懒加载,在创建View的时候就会调用viewDidLoad方法,之前在TabBarController的addChildVc方法中,设置了每个View的随机色,用于测试,此时就会调用viewDidLoad方法,设置enable,而在这之后才会去调用下面的自定义导航控制器,里面再去设置主题,导致调用顺序先后出现问题,因此Item没有显示灰色!!!
注2:而且若设置随机色,则四个控制器的view均一口气创建完(均会调用viewDidLoad方法),这种做法不对,应该在需要使用相应控制器的时候再去创建控制器的view,将设置随机色的代码注释掉即可,且可将设置Item的enable放到viewDidLoad方法中!