Skip to content

iOS APP框架搭建简析

仁伯安 edited this page Feb 6, 2017 · 1 revision

奋斗.png

前言

不管开发任何软件,我们的原则就是尽量做到“高内聚低耦合”。所谓“低耦合”是指软件结构中模块与模块之间的耦合度或关联程度,模块之间接口的调用及实现的复杂度、交互数据的多少等,决定了软件耦合度的高低强弱;所谓“高内聚”是从模块内部功能的层面而言的,模块内部特定功能的代码元素的紧密程度决定了代码内聚性的高低。

网上不乏有所谓“十分钟搭建强壮APP框架”、“快速搭建强壮APP框架”等帖子,且不去讲好坏,总之,实践是检验真理的唯一标准,今天我简单汇报下本人做项目时,框架的搭建流程及注意事项。

框架搭建

框架搭建是个劳神费心的事情,因为在搭建时你要考虑到各种可能,比如:怎么设计使得流程更清晰?怎么设计更易于分工协作?怎么设计更容易快速定位代码模块?怎么保证系统的易扩展性?等等都是我们要提前把握好的。先看下大致效果图如下: 启动图效果.png 最终效果.gif

一、 框架结构

APP的结构一般分为三条线:

  • 一条主框架流程;
  • 一条是用户登录框架流程;
  • 一条其他如广告页、欢迎页等

相对而言,主框架流程较为复杂,顶级容器为UITabBarController,子容器为UINavigationController,其中顶级容器放3-5个导航控制器,导航控制器的rootViewController为各模块的首页。登录框架流程及其他一般为线性流程,个别会涉及到根视图的切换,相对简单,如果画成树状结构图的话大致如下: APP结构图.png

二、 StoryBoard分离

为了配置三方库方便,我使用CocoaPods工程(基于CocoaPods 1.1.1),下为Podfile文件引入的三方库:

platform :ios,’8.0’

target ‘EVNEstorePlatform’ do

pod 'MBProgressHUD', '~> 1.0.0'
pod 'FMDB'
pod 'SDWebImage', '~> 3.8'
pod 'IQKeyboardManager', '~> 3.3.7'
pod 'MJRefresh'
pod 'MJExtension'
pod 'MWPhotoBrowser'
pod 'AFNetworking', '~> 3.0'

end

如遇到问题,可参照CocoaPods工作原理及使用中遇到的问题,解决或问阿度。

在实际的项目开发中,没有说谁的框架更优,结构都是大同小异,适合自己的团队才是最重要的。单从框架搭建及界面布局而言,有的团队喜欢StoryBoard,因为所见即所得,给外行介绍起来较为方便,一个模块的所有的界面铺满屏幕,很酷炫的感觉。有的团队喜欢纯代码,当看到自己写一串串字符渲染出“神秘”动画,说不出的满足感。当然我们团队奉行的是中庸之道,框架搭建+个别简易界面我们使用StoryBoard,其他使用纯代码的方式,这也是踩过坑之后,倒逼的结果。 StoryBoard.png 毋庸置疑StoryBoard有很多的优点,但对于团队协作开发,有时会有说不出的痛,比如:同时修改StoryBoard文件遇到的冲突;即便是细微的位移调整,编译起来也需要足够耐心;更新了下Xcode怎么布局全乱了等等问题,正因为此,我们采用折中方案,尽量将StoryBoard分离使用,Main.storyboard中为主框架顶级容器和登录流程的顶级容器,而其他3-5个模块如,首页Host.storyboard、个人中心MineCenter.storyboard等,使用单独的StoryBoard文件,除此之外基本使用纯代码方式编写。 模块.png

MainStoryBoard.png

MineCenterStoryBoard.png

在进行故事版分离时,主要是自定义UITabBarController的过程。 首先,根据上面模板图,新建故事版文件; 然后,按照第一节框架结构图,将特定的控制器容器、导航控制器、视图控制器拖入对应的故事版中(StoryBoard文件); 再次,在自定义的UITabBarController中,连接各个模块,在这个过程中UITabBarController起到了应用的连接中枢的作用,为了炫技,哥做了个中间凸起效果,主要的TabBarController代码如下:

#pragma mark: 首页storyboard
    UIImage *hostSelectImg = [UIImage imageNamed:@"hostViewSelect"];
    UIImage *hostUnSelectImg = [UIImage imageNamed:@"hostViewUnSelect"];
    UIStoryboard *hostSB = [UIStoryboard storyboardWithName:@"Host" bundle:nil];
    UINavigationController *hostNaviVC = [hostSB instantiateViewControllerWithIdentifier:@"hostNavigationC"];
    hostNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首页" image:[self scaleImage:hostUnSelectImg] selectedImage:[self scaleImage:hostSelectImg]];
    hostNaviVC.tabBarItem.tag = 0;

#pragma mark: 关注storyboard
    UIImage *attentionSelectImg = [UIImage imageNamed:@"attentionSelect.png"];
    UIImage *attentionUnSelectImg = [UIImage imageNamed:@"attentionUnSelect.png"];
    UIStoryboard *attentionSB = [UIStoryboard storyboardWithName:@"Attention" bundle:nil];
    UINavigationController *attentionNaviVC = [attentionSB instantiateViewControllerWithIdentifier:@"attentionNavigationC"];
    attentionNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"关注" image:[self scaleImage:attentionUnSelectImg] selectedImage:[self scaleImage:attentionSelectImg]];
    attentionNaviVC.tabBarItem.tag = 1;

#pragma mark: 发现storyboard
    UIImage *findSelectImg = [UIImage imageNamed:@"findSelect.png"];
    UIImage *findUnSelectImImg = [UIImage imageNamed:@"findUnSelect.png"];
    UIStoryboard *findSB = [UIStoryboard storyboardWithName:@"Find" bundle:nil];
    UINavigationController *findNaviVC = [findSB instantiateViewControllerWithIdentifier:@"findNavigationC"];
    findNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"发现" image:[UIImage imageWithCGImage:findUnSelectImImg.CGImage scale:1.5 orientation:findUnSelectImImg.imageOrientation] selectedImage:[UIImage imageWithCGImage:findSelectImg.CGImage scale:1.5 orientation:findSelectImg.imageOrientation]];
    [findNaviVC.tabBarItem setImageInsets:UIEdgeInsetsMake(-14, 0, 14, 0)];
    findNaviVC.tabBarItem.tag = 2;
    findNaviVC.tabBarItem.selectedImage = [[UIImage imageNamed:@"findSelect.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    findNaviVC.tabBarItem.image = [[UIImage imageNamed:@"findUnSelect.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

#pragma mark: 购物车storyboard
    UIImage *goodsCarSelectImg = [UIImage imageNamed:@"goodsCarSelect.png"];
    UIImage *goodsCarUnSelectImg = [UIImage imageNamed:@"goodsCarUnSelect.png"];
    UIStoryboard *goodsCarSB = [UIStoryboard storyboardWithName:@"GoodsCar" bundle:nil];
    UINavigationController *goodsCarNaviVC = [goodsCarSB instantiateViewControllerWithIdentifier:@"goodsCarNavigationC"];
    goodsCarNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"购物车" image:[self scaleImage:goodsCarUnSelectImg] selectedImage:[self scaleImage:goodsCarSelectImg]];
    goodsCarNaviVC.tabBarItem.tag = 3;

#pragma mark: 个人中心storyboard
    UIImage *mineCenterSelectImg = [UIImage imageNamed:@"mineCenterSelect.png"];
    UIImage *mineCenterUnSelectImg = [UIImage imageNamed:@"mineCenterUnSelect.png"];
    UIStoryboard *mineCenterSB = [UIStoryboard storyboardWithName:@"MineCenter" bundle:nil];
    UINavigationController *mineCenterNaviVC = [mineCenterSB instantiateViewControllerWithIdentifier:@"mineCenterNavigationC"];
    mineCenterNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我" image:[self scaleImage:mineCenterUnSelectImg] selectedImage:[self scaleImage:mineCenterSelectImg]];
    mineCenterNaviVC.tabBarItem.tag = 4;

#pragma mark: 连接
    self.viewControllers = @[hostNaviVC, attentionNaviVC, findNaviVC, goodsCarNaviVC, mineCenterNaviVC];

最后, 创建各模块对应的视图控制器,将其匹配到StoryBoard中的控件中。 框架目录.png

三、 APP使用流程

APP运行的流程一般为,首先执行AppDelegate的代理方法didFinishLaunching,进入启动页,判断是否是首次使用APP,如果是进入欢迎页,否则直接验证广告页验证,进而进入加载广告页,最后进入首页。具体流程图如下: APP流程图.png 我的框架也是根据这个流程搭建。

结语

战战兢兢,如履薄冰,望再接再厉,下为工程托管地址,EVNEstorePlatform GitHub,如果觉得有帮助,请不要吝啬点赞,可以在GitHub给个star,O(∩_∩)O谢谢......

Clone this wiki locally