当前位置:首页 期刊杂志

iOS APP中框架的搭建及TabBar的自定义创建的分析

时间:2024-06-19

张 华,杨凯淇

(1.长春工程学院计算机技术与工程学院,长春 130012;2.哈尔滨工业大学电气工程及自动化学院,哈尔滨 150001)

iOS APP中框架的搭建及TabBar的自定义创建的分析

张 华1,杨凯淇2

(1.长春工程学院计算机技术与工程学院,长春 130012;2.哈尔滨工业大学电气工程及自动化学院,哈尔滨 150001)

在设计一个iOS APP时,首先要分析其所有的功能并进行按模块划分,然后要根据划分出来的模块进行整体框架的搭建和TabBar的设计,两者的合理设计对整个APP有重要影响,以新浪微博为例,详细介绍了APP中框架的搭建和TabBar的自定义创建。

iOS APP;框架;TabBar;新浪微博

0 引言

在当今互联网时代,智能手机广泛应用,人们工作、生活、学习中的很多方面都可以通过网络借助手机APP来完成,比如:微信、大众点评、腾讯视频、扇贝单词等,可以说,手机APP已经变成人们工作和生活中不可或缺的一部分,也使得APP开发有很大的市场。在开发APP时,因为各自功能和业务逻辑都不相同,具体实现过程也就不同,但开发思路都是一样的,整个APP的框架搭建和主功能栏TabBar的实现至关重要,本文借助于新浪微博APP就这两方面进行阐述,掌握了这两方面的技巧,也就可以得心应手地去开发各类APP。

1 iOS APP中框架的搭建

在设计智能终端APP时,整体框架的搭建相当于是APP的灵魂,一个合适的框架,不但能保证工程可以顺利进行,还能够降低通用问题的复杂度和减少发生错误的可能性,现在流行的APP架构主要有MVC和MVVM。

1.1 MVC架构

MVC:Model-View-Controller,模型Model通常是Core Data managed objects,包括数据和操作数据的业务逻辑;视图View通常是UIKit控件或者编码定义的UIKit控件的集合,比如:Button、Label,View不直接引用Model,并且仅仅通过IBAction事件引用Controller,业务逻辑不归入view,视图本身没有任何业务;控制器Controller负责协调模型和视图之间的所有交互。

图1 MVC架构

在上图中,View将用户交互通知给Controller。View Controller通过更新Model来反应状态的改变。Model(通常使用Key-Value-Observation)通知Controller来更新它们负责的View。大多数iOS应用程序的代码使用这种方式来组织。

1.2 MVVM架构

在MVC模式的iOS开发中,Controller承担了太多的代码,包含着视图处理逻辑和业务逻辑。MVVM:Model-View-ViewModel,这种模型通常应用在UIKit控件不能设置固定高度,必须根据显示内容多少而决定的情况下。View Model用来放置用户输入验证逻辑、视图显示逻辑、发起网络请求等代码。

图2 MVVM架构

在上图中,View和View Controller联系在一起,可以把它们视为一个组件。视图View仍然不能直接引用模型Model,控制器Controller也不能,但是它们都可以引用视图模型View Mode。在MVVM中,将视图处理逻辑从C中剥离出来给V,剩下的业务逻辑部分被称做View-Model。使用MVVM模式的iOS应用的可测试性要好于MVC,因为ViewModel中并不包含对View的更新,相比于MVC,减轻了Controller的负担,使功能划分更加合理。MVVM模式的正确实践是,应该为App Delegate的根视图创建一个ViewModel,当我们要生成或展示另一个次级ViewController时,采用当前的ViewModel为其创建一个子ViewModel。

1.3 新浪微博的框架搭建

大家所熟悉的新浪微博的主界面,如图3所示,主功能分为五大模块:首页、消息、发现、我、还有中间的“+”(即发微博)。

图3 新浪微博主界面

按照微博APP的主功能设计,将项目中的文件按照MVC框架进行划分,每个模块都细分为MVC 3部分,扩展分类、网络访问、第三方组件、基础工具类、图片等都分别存放,具体划分如图4所示:具体文件夹说明如下:

1)Classes:APP类文件都存放在此文件夹,包含以下子文件夹:

Main:存放APP主界面文件,如:TabBar;

Home:存放“首页”模块中的所有文件;

Message:存放“消息”模块中的所有文件;

Discover:存放“发现”模块中的所有文件;

Profile:存放“我”模块中的所有文件;

Compose:存放“+”模块,即发微博模块中的所有文件;

Setting:存放个人设置模块中的所有文件;

Newfeature:存放新特性模块中的所有文件;

OAuth:存放授权模块中的所有文件;

图4 微博项目文件结构

以上文件夹下均包含Model、View、Controller 3个子文件夹分别用来存放各模块的模型、视图和控制器。

Base:存放通用、基础功能的文件;

Tool:存放各种业务逻辑的操作文件,如:网络访问的各文件;

Other:访问各种其他文件,如分类文件、第三方组件、APP启动文件AppDelegate等。

2)images:存放普通图片。

3)Assets.xcassets:管理应用的Icon和Default图片,自动管理图片。

4)Supporting Files:存放APP配置文件等辅助文件。

每个文件夹下都可以根据功能设计再划分各子文件夹,这样划分,层次清楚、逻辑清晰,可以灵活地管理各个模块,也可以方便地替换网络访问层和第三方组件,以便完成APP更新升级。

2 iOS APP中TabBar的自定义创建

2.1 系统自带的TabBar

在APP的启动文件AppDelegate中需要设置要启动的TabBarController,即工具条控制器,APP界面下方的工具条称为TabBar,高度固定为49,如果TabBarController有N个子控制器,那么TabBar内部就会有N个TabBarButton作为子控件与之对应,TabBarButton在TabBar中的位置是均分的,TabBarButton里面显示什么内容,由对应子控制器的TabBarItem属性来决定,TarBarButton右上角显示更新数目的称为BadgeView,如图5~6所示:

图5 微信APP界面底部的TabBar

图6 微博APP界面底部的TabBar

图5中的TabBar实现方法较为简单,可以直接使用系统自带的TabBar来完成,分别创建各个TabBarButton对应的TabBarController,然后添加到TabBarController中即可,使用系统自带的TabBar创建微博APP的TabBar,大致代码如下:

-(void)setUpAllChildViewController{

//首页

UIViewController *home=[[UIViewControlleralloc]init];

[self setUpOneChildViewController:home image:[UIImageimageNamed:@"tabbar_home"] selectedImage:[UIImageimageWithOriginalName:@"tabbar_home_selected"] badgeValue:@"10" title:@"首页"];

//消息

UIViewController*message=[[UIViewControlleralloc]init];

[self setUpOneChildViewController:message image:[UIImageimageNamed:@"tabbar_message_center"] selectedImage:[UIImageimageWithOriginalName:@"tabbar_message_center_selected"] badgeValue:@"10" title:@"消息"];

//发现

UIViewController*discover=[[UIViewControlleralloc]init];

[self setUpOneChildViewController:discover image:[UIImageimageNamed:@"tabbar_discover"] selectedImage:[UIImageimageWithOriginalName:@"tabbar_discover_selected"] badgeValue:@"10" title:@"发现"];

//我

UIViewController*profile=[[UIViewControlleralloc]init];

[self setUpOneChildViewController:profile image:[UIImageimageNamed:@"tabbar_profile"] selectedImage:[UIImageimageWithOriginalName:@"tabbar_profile_selected"] badgeValue:@"10" title:@"我"];

}

-(void)setUpOneChildViewController:(UIViewController *)vc image:(UIImage *)image selectedImage:(UIImage *)selectedImage title:(NSString *)title {

vc.title=title; //设置当前VC的标题,显示在导航栏中

vc.tabBarItem.title=title;

vc.tabBarItem.image=image; //设置图片

vc.tabBarItem.selectedImage=selectedImage;

//将每个VC的tabBarItem添加到items数组中

[self.itemsaddObject:vc.tabBarItem];

}

2.2 自定义的TabBar

系统自带的TabBar不能更改TabBarButton上的BadgeView,因为其继承自UIView且没有更改image的属性或者方法,所以只能使用BadgeView的默认效果,通常情况下,这种效果不能满足大众需要,另外,图6中的TabBar除了四个普通的TabBarButton外,中间还有一个自定义的按钮“+”,这种情况下,系统自带的TabBar也无法实现。综合以上两方面的原因,需要自定义TabBar重新封装,此次封装既解决BadgeView的问题,也替换了TabBar中的各个按钮。自定义创建TabBar的步骤如图7所示。

在单击TabBar上的各个按钮实现界面切换时,实际上是在TabBar视图上单击按钮,在TabBarController上实现控制器的切换,所以要在TabBar视图中声明协议和代理,在TabBarController上通过代理完成协议中的方法。

自定义TabBar的具体步骤及相关代码如下:

1)创建每个按钮对应的ViewController:在Main文件夹的Controller文件夹上分别创建WBHomeViewController(首页)、WBMessageViewController(消息)、WBDiscoverViewController(发现)、WBProfileViewController(我)、WBComposeViewController(发微博“+”),继承自UITableViewController。

2)创建主视图控制器TabBarViewController:在Main文件夹的Controller文件夹上创建WBTabBarController,继承自UITabBarViewController,声明一个items数组来保存每个子控制器的tabBarItem,items要使用懒加载。引用步骤(1)中创建的各子控制器并声明对应的对象,调用之前的setUpAllChildViewController实现各子控制器的加载,修正之前的在此方法中需要将原来的UIViewController更改为各具体的子控制器。大致代码如下:

图7 自定义TabBar的创建步骤

@property(nonatomic,strong)NSMutableArray*items;

@property(nonatomic,strong)WBHomeViewController*home;

-(void)setUpAllChildViewController{

//首页

WBHomeViewController*home=[[WBHomeViewControlleralloc]init];

[self setUpOneChildViewController:home image:[UIImageimageNamed:@"tabbar_home"] selectedImage:[UIImageimageWithOriginalName:@"tabbar_home_selected"] badgeValue:@"10" title:@"首页"];

_home=home;

……

}

setUpOneChildViewController方法在原来的代码的基础上要增加为items数组赋值。

-(void)setUpOneChildViewController:(UIViewController *)vc image:(UIImage *)image selectedImage:(UIImage *)selectedImage title:(NSString *)title {

…..

//将每个VC的tabBarItem添加到items数组中

[self.itemsaddObject:vc.tabBarItem];

}

3)创建TabBar视图:在Main文件夹的View上新建WBTabBar类,继承自UIView而不是UITabBar。声明一个items数组,用来接收WBTabBarController中传递过来的包含各子控制器tabBarItem的items数组,根据此数组来设定在TabBar上显示的TabBarButton的数量及内容。

4)创建显示未读数目的BadgeView按钮:在Main文件夹的View文件夹上新建WBBadgeView文件,继承自UIButton。在.h头文件里,设置一个badgeValue属性,属于NSString对象,重写initWithFrame方法实现按钮的创建及初始化,重写badgeValue的set方法,每当有值传过来的时候都会调用这个方法,刷新Button上显示的信息,在代码中要判断传入来的badgeValue值是否为空或者是0,以此决定Button上是否显示,然后根据传入文字的大小,决定应该显示什么图片。

5)创建自定义TabBarButton按钮:在Main文件夹的View上新建WBTabBarButton类,继承自UIButton。在头文件里声明UITabBarItem对象item来保存从TabBar内得到的TabBarItem模型,根据模型可以设置每个按钮的内容。在每个按钮的右上方需要显示未读数目,需要引入步骤4)中创建的WBBadgeView,然后重写initWithFrame设置按钮的文字和图片等基本信息,重写layOutSubviews方法调整文字、图片的尺寸和位置。大致代码如下:

@property(nonatomic,weak)WBBadgeView *badgeView;

-(WBBadgeView *)badgeView

{

if(_badgeView == nil){

WBBadgeView *badgeView = [WBBadgeViewbuttonWithType:UIButtonTypeCustom];

[selfaddSubview:badgeView];

_badgeView = badgeView;

}

return _badgeView;

}

6)给自定义的TabBarButton添加监听事件:使用KVO监听TabBarItem的属性,当模型更改的时候,视图也跟着更改。系统默认模型改变的时候,不刷新视图,需要手动调用KVO,在对象被销毁时,清空观察者。重写item 的set方法,传递UITabBarItem的信息给WBTabBarButton并实现监听。

7)设置自定义WBTabBar视图中的协议和代理:声明一个数组buttons用来保存视图中的所有按钮,给每个TabBarButton添加监听按钮点击的方法,4个普通按钮和1个“+”按钮分别添加,以用于控制器的切换。因为控制器的切换是由WBTabBarController控制的,所以需要给WBTabBar添加代理属性,4个普通按钮和1个“+”按钮分别添加,两个代理,在TabBarButton点击时,会通知WBTabBarController切换控制器。在四个普通按钮的代理方法中设定角标参数,把按钮的tag传递出去。头文件.h文件中的大致代码如下:

//设置代理

@class WBTabBar;

@protocol WBTabBarDelegate //声明协议

@optional

//规定协议中要完成的动作即代理要实现的方法,即回调函数,在外界的ViewController中要具体实现

-(void)tabBar:(WBTabBar *)tabBardidSelectedIndex:(NSInteger)selectedIndex;

-(void)tabBarDidClickAddBtn:(WBTabBar *)tabBar;

@end

@interface WBTabBar : UIView //由原来的UITabBar更改为UIView

// items:保存每一个按钮对应tabBarItem模型

@property(nonatomic,strong)NSArray *items;

@property(nonatomic,weak)id delegate;//声明一个代理

@end

8)在WBTabBarController中完成协议中规定的方法:遵守WBTabBar中规定的协议,WBTabBarController成为WBTabBar的代理,实现协议里规定的两个代理方法,大致代码如下:

@interface WBTabBarController() //继承协议,完成按钮点击

@property(nonatomic,assign)NSIntegerselIndex;//保存被选中按钮的tag

//重写WBTabBar协议中的代理方法,当在WBTabBar中监听到TabBar被点击时就会调用此方法

-(void)tabBar:(WBTabBar *)tabBardidSelectedIndex:(NSInteger)selectedIndex

{

self.selectedIndex = index;

}

// 重写WBTabBar协议中代理方法,当在WBTabBar中监听到"+"被点击时就会调用此方法

-(void)tabBarDidClickAddBtn:(WBTabBar*)tabBar

{

//具体完成点击发微博按钮时的动作

}

到此为止,自定义的TabBar工具条就实现了。

3 结语

MVVM框架是对MVC的改进,可以跟 storyboard一样用来显示高度不固定的内容,自定义TabBar对初学者可能比较绕,本质上就是一层一层的值传递,直到把值传递给最应该需要的那个控件或者类,这是一种正向思维,还有一种是逆向思维,直接推测WBTabBarButton需要什么样的值才能建立好所需要展示的TabBarButton。一想便知它需要图片、文字等信息,而思考这些信息保存在哪里,如何能得到,便是一种逆向思维。无论使用哪种思维,只要思路清晰、逻辑正确,就可以创建出各式各样的自定义TabBar。

[1] 唐巧.iOS开发进阶[M]. 北京:电子工业出版社,2014.

[2] 纳皮尔,库玛.iOS编程实战[M]. 北京:人民邮电出版社,2014.

[3] 李宜为.基于iOS自由行客户端的设计与实现[D].北京:北京交通大学2015.

The Construction of iOS APP Framework and the Analysis of the Self-defined Creation of Tab Barin

ZHANG Hua,et al.

(SchoolofComputerTechnology&Engineering,ChangchunInstituteofTechnology,Changchun130012,China)

During the design an iOS APP,all the functions should be firstly analyzed and module classifications should be made.Then the whole framework construction and Tab Bar design should be done according to the classified modules.The reasonable design to both parts is important to the whole APP.Taking Sina Weibo as an example,this paper introduces in detail the framework construction in APP and the self-defined creation of Tab Bar.

iOS APP;framework;TabBar;SinaWeibo

10.3969/j.issn.1009-8984.2016.04.026

2016-11-08

张华(1981-),女(汉),山东泰安,讲师,硕士 主要研究数字图像处理、数据挖掘。

TP391

A

1009-8984(2016)04-0100-05

免责声明

我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!