实现:仿新浪微博


1、项目配置



1> 取消横竖屏

2> 设置图标和启动图片

3> 删除MainStoryboard,全部代码创建


ios 项目结构图 ios项目框架搭建_ios 项目结构图


2、添加TabBarController


2.1 创建窗口



1>在didFinishLaunchingWithOptions方法中,创建窗口,设置根控制器,显示窗口


ios 项目结构图 ios项目框架搭建_TabBarController_02


2> 添加TabBarController的子控制器


ios 项目结构图 ios项目框架搭建_ios 项目结构图_03


ios 项目结构图 ios项目框架搭建_TabBarController_04



3>抽取重复代码


ios 项目结构图 ios项目框架搭建_iOS开发_05


ios 项目结构图 ios项目框架搭建_TabBarController_06



注:上述方法限制每次创建的都是UIViewController,实际使用中,需要设置不同的控制器作为TabBarController的子控制器


4> 改进

添加HWHomeViewController等控制器,在创建后传递给上述设置方法,设置Item和图片


ios 项目结构图 ios项目框架搭建_iOS开发_07


ios 项目结构图 ios项目框架搭建_TabBarController_08


2.2 自定义HWTabBarViewController



注:上述创建的四个控制器应该属于TabBarController,由TabBarController去管理,而且HWAppDelegate代理的功能主要是创建窗口,设置根控制器TabBarController,不需要管TabBarController里面的具体实现,因此上述代码不应该放在HWAppDelegate方法中,应该单独抽取出来,在HWTabBarViewController的viewDidLoad方法中实现添加子控制器


ios 项目结构图 ios项目框架搭建_NavigationController_09


ios 项目结构图 ios项目框架搭建_ios 项目结构图_10


3、添加NavigationController


3.1 项目结构


ios 项目结构图 ios项目框架搭建_iOS开发_11


ios 项目结构图 ios项目框架搭建_ios 项目结构图_12


3.2 包装导航控制器


ios 项目结构图 ios项目框架搭建_UIBarButtonItem_13


3.3 导航控制器跳转


1> HWMessageCenterViewController假数据


ios 项目结构图 ios项目框架搭建_NavigationController_14


2> 点击Cell跳转


ios 项目结构图 ios项目框架搭建_ios 项目结构图_15


4、自定义导航控制器


4.1 设置导航控制器leftBarButtonItem和rightBarButtonItem


ios 项目结构图 ios项目框架搭建_ios 项目结构图_16



箭头:返回上一个控制器

三点:返回导航控制器的根控制器


1> 基本实现


ios 项目结构图 ios项目框架搭建_TabBarController_17


注:对于自定义UIButton(或者其他UI控件),必须设置其尺寸,否则可能不会显示!!!



注:UIView写分类

注:当需要修改控件的尺寸的时,往往需要先取出frame,再修改frame,最后再设置frame,比较麻烦,可以写一个UIView的分类,封装修改尺寸的方法!


ios 项目结构图 ios项目框架搭建_UIBarButtonItem_18



重写上面上述属性的setter/getter方法,设置/取出控件frame,再将头文件写到pch文件中,其他类可以直接调用


ios 项目结构图 ios项目框架搭建_NavigationController_19



2>其他控制器跳转时也实现上述要求

若其他控制器跳转时,也需要实现设置导航控制器为同样的Item,则直接将上述代码复制到每个控制器的viewDidLoad方法中即可。

但是,若控制器很多,则上述重复代码复制太多,应该抽取出来。

方法一:考虑继承

但是对于控制器来说,一般不使用继承,因为控制器种类很多,不可能将所有控制器继承自同一个控制器,通过一个控制器来实现统一。

比如:导航控制器中既有UIViewController,又有UITableViewController,且需要同时设置导航控制器的Item,则不能通过继承同一个控制器,设置其Item来实现。

方案二:自定义导航控制器

重写push方法,就可以得到传进来的控制器参数


4.2 自定义导航控制器



1> 在3.2节中,包装导航控制器添加到HWTabBrViewController中时,包装的导航控制器为自定义导航控制器

2>重写自定义导航控制器的push方法!!!


ios 项目结构图 ios项目框架搭建_TabBarController_20


ios 项目结构图 ios项目框架搭建_iOS开发_21



注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方法中设置。


ios 项目结构图 ios项目框架搭建_UIBarButtonItem_22



注:带来问题,每个根控制器都需要这样设置左右的Item,而且代码跟导航控制器的push方法中设置Item的代码重复


6.2 初步封装


ios 项目结构图 ios项目框架搭建_UIBarButtonItem_23


将HWHomeViewController中的Item创建方法抽取出来,但是这样只能保证在HWHomeViewController中能够快速创建,在其他控制器中仍然需要重复代码创建。


6.3 创建UIBarButtonItem分类


ios 项目结构图 ios项目框架搭建_ios 项目结构图_24



注意:一定要添加target参数,用于表示哪个对象,如果直接将上面的代码复制过来是self,会导致点击Item的时候调用分类的action方法(属于控制器,不属于Item),程序崩溃!!!并将头文件放到pch文件中。则在需要创建Item的时候,直接调用分类的方法即可!!!


如:

ios 项目结构图 ios项目框架搭建_ios 项目结构图_25


7、小结


ios 项目结构图 ios项目框架搭建_UIBarButtonItem_26


8、设置导航栏主题


ios 项目结构图 ios项目框架搭建_iOS开发_27



注:消息控制器中设置导航栏右边Item(写私信)不使能,若将enable = NO放到viewDidLoad方法中,主体来不及渲染,会没有显示灰色,应该放在viewWillAppear方法中


ios 项目结构图 ios项目框架搭建_TabBarController_28


注1:造成上述问题的主要原因是:由于View采用的是懒加载,在创建View的时候就会调用viewDidLoad方法,之前在TabBarController的addChildVc方法中,设置了每个View的随机色,用于测试,此时就会调用viewDidLoad方法,设置enable,而在这之后才会去调用下面的自定义导航控制器,里面再去设置主题,导致调用顺序先后出现问题,因此Item没有显示灰色!!!


ios 项目结构图 ios项目框架搭建_NavigationController_29



注2:而且若设置随机色,则四个控制器的view均一口气创建完(均会调用viewDidLoad方法),这种做法不对,应该在需要使用相应控制器的时候再去创建控制器的view,将设置随机色的代码注释掉即可,且可将设置Item的enable放到viewDidLoad方法中!