详解iOS项目基本框架搭建

项目开发过程中,在完成iOS项目——项目开发环境搭建之后,我们首先需要考虑的就是我们的项目的整体框架与导航架构设计,然后在这个基础上考虑功能模块的完成。

一 导航架构设计

一款App的导航架构设计应该是符合人们的操作惯性和方便操作的特点,也应该在交互上更加合理和人性化。根据项目功能和定位不同,不同的App的导航设计应该采用不同的技术框架,目前比较常见的导航框架主要有标签式、列表式、矩阵式三大类,如下图。

目前资讯新闻类的移动端项目的主流App框架基本都是标签式的,这种类型的导航设计技术上基本上都是通过TabBar + NavigationController框架进行搭建完成,大家经常使用到的微博、今日头条等都是采用TabBar + NavigationController这样的框架。TabBar + NavigationController就是在应该TabBar上添加itemBar,每一个itemBar都是一个独立的模块,并且每一个itemBar都对应一个NavigationController。因为每一个itemBar的导航器都不一样,所以应该是先有TabBar 再有NavigationController。

我们的项目也属于资讯类,所以我们的项目的框架也是采用TabBar + NavigationController进行搭建。今天我们的主要任务就是搭建我们TabBar,如果采用系统自带的UITabBarController(官网文档戳这里),在使用过程有一下几点需要注意:

每一个barItem都必须对应一个ViewController,可以是一般的ViewController,也可以是UINavigationController barItem对应的ViewController或UINavigationController的frame如果自定义设置了,注意不要遮挡最下面的TabBar条 barItem的顺序与添加到UITabBarController的顺序保持一致当添加的barItem个数 <= 5个时,均匀分布在最下面的bar条上,如上图所示的4个当添加的barItem个数 > 5个时,会只显示前四个添加的barItem,然后加上一个【more】,点击【more】弹出一个列表可选,并且列表的右上角有一个【edit】按钮,点击之后可以调整barItem的显示顺序,如下图所示,所以TabBar + NavigationController框架下的barItem个数最好不要超过5个,否则用户体验不是很好

添加itemBar对应的ViewController的方法有两种:一是使用UITabBarController的 setViewControllers: 方法设置;二是用UIViewController的 addChildViewController: 方法添加子视图,也可以实现添加到tabBar的功能,但是这种方法对于barItem个数 > 5的时候,只会显示前五个,剩下的不会出现时出来,也没有【more】按钮可以选择。

示例代码如下,自定义一个TabBarController继承自UITabBarController,然后重写其 viewDidLoad 方法添加子视图和标签:

@implementation XMGTabBarController

- (void)viewDidLoad {
  [super viewDidLoad];

  //添加4个item bar
  UITableViewController *vc0 = [[UITableViewController alloc] init];
  vc0.view.backgroundColor = [UIColor redColor];
  vc0.tabBarItem.title = @"精华";
  vc0.tabBarItem.image = [UIImage imageNamed:@"tabBar_essence_icon"];
  vc0.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_essence_click_icon"];
  [self addChildViewController:vc0];

  UIViewController *vc1 = [[UIViewController alloc] init];
  vc1.view.backgroundColor = [UIColor blueColor];
  vc1.tabBarItem.title = @"新帖";
  vc1.tabBarItem.image = [UIImage imageNamed:@"tabBar_new_icon"];
  vc1.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_new_click_icon"];
  [self addChildViewController:vc1];

  UITableViewController *vc2 = [[UITableViewController alloc] init];
  vc2.view.backgroundColor = [UIColor greenColor];
  vc2.tabBarItem.title = @"关注";
  vc2.tabBarItem.image = [UIImage imageNamed:@"tabBar_friendTrends_icon"];
  vc2.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_friendTrends_click_icon"];
  [self addChildViewController:vc2];

  UIViewController *vc3 = [[UIViewController alloc] init];
  vc3.view.backgroundColor = [UIColor grayColor];
  vc3.tabBarItem.title = @"我";
  vc3.tabBarItem.image = [UIImage imageNamed:@"tabBar_me_icon"];
  vc3.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_me_click_icon"];
  [self addChildViewController:vc3];

   //下面的方法也是可以的,推荐使用下面的方法
//  [self addChildViewController:@[vc0,vc1,vc2,vc3]];

}

二 开发过程中注意代码重构

在开发过程中,我们最好不要重复写相同的代码,因此,在开发过程中,我们需要对我们的代码进行重构和简化,主要原则是尽量保持一个方法实现一个功能,然后尽量不写重复的代码,精简逻辑。在我们前面添tabBar item的代码中就存在大量重复性的代码,所以我们需要对其进行重构,将重复性的代码进行抽取,将不同的内容设置成参数进行自定义设置,重构后的逻辑如下:

@implementation XMGTabBarController

- (void)viewDidLoad {
  [super viewDidLoad];

  /**** 添加子控制器 ****/
  [self setupOneChildViewController:[[UITableViewController alloc] init] title:@"精华" image:@"tabBar_essence_icon" selectedImage:@"tabBar_essence_click_icon"];
  [self setupOneChildViewController:[[UITableViewController alloc] init] title:@"新帖" image:@"tabBar_new_icon" selectedImage:@"tabBar_new_click_icon"];
  [self setupOneChildViewController:[[UIViewController alloc] init] title:@"关注" image:@"tabBar_friendTrends_icon" selectedImage:@"tabBar_friendTrends_click_icon"];
  [self setupOneChildViewController:[[UITableViewController alloc] init] title:@"我" image:@"tabBar_me_icon" selectedImage:@"tabBar_me_click_icon"];
}

/**
 * 初始化一个子控制器
 *
 * @param vc      子控制器
 * @param title     标题
 * @param image     图标
 * @param selectedImage 选中的图标
 */
- (void)setupOneChildViewController:(UIViewController *)vc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
  vc.view.backgroundColor = [UIColor redColor];
  vc.tabBarItem.title = title;
  vc.tabBarItem.image = [UIImage imageNamed:image];
  vc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage];
  [self addChildViewController:vc];
}

@end

三 UITabBarItem设置

在iOS开发过程中,系统自带的空间有时候会将有些图片显示出来时自动渲染成蓝色,例如自带的TabBarItem在选中时的图片,还有设置UIButtonTypeSystem样式时按钮的图片,这时候系统都会自动渲染成蓝色。

vc.tabBarItem.selectedImage = image;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setImage:image forState:UIControlStateNormal];

3.1 image的渲染问题  

我们在开发过程中有时候并不需要这种渲染,只希望开发的App按我们设定的图片进行显示就好了,这是我们就需要对图片进行禁止渲染的设定和操作。有两种解决方案:

再次产生一张不会进行渲染的图片

// 加载图片
UIImage *tempImage = [UIImage imageNamed:@"tabBar_essence_click_icon"];
// 产生一张不会进行自动渲染的图片
UIImage *selectedImage = [tempImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc.tabBarItem.selectedImage = selectedImage;

直接在xcassets文件中配置图片不被渲染

3.2 设置TabBarItem的文字属性

在上述我们队图片修改之后,虽然tabBarItem的图片可以完全按照我们设定的图片进行显示,但是 在开发过程中,我们很多时候还需要对tabBarItem的标题的字体、字号等文字属性进行设定。要设定tabBarItem的文字属性,我们也有两种解决方案:

直接设置每一个tabBarItem对象

// 普通状态下的文字属性
NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
normalAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:14];
normalAttrs[NSForegroundColorAttributeName] = [UIColor grayColor];
[vc.tabBarItem setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];

// 选中状态下的文字属性
NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
selectedAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[vc.tabBarItem setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];

需要注意的是:

// 字典中用到的key
1.iOS7之前(在UIStringDrawing.h中可以找到)
- 比如UITextAttributeFont\UITextAttributeTextColor
- 规律:UITextAttributeXXX
2.iOS7开始(在NSAttributedString.h中可以找到)
- 比如NSFontAttributeName\NSForegroundColorAttributeName
- 规律:NSXXXAttributeName

通过UITabBarItem的appearance对象统一设置

/**** 设置所有UITabBarItem的文字属性 ****/
UITabBarItem *item = [UITabBarItem appearance];
// 普通状态下的文字属性
NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
normalAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:14];
normalAttrs[NSForegroundColorAttributeName] = [UIColor grayColor];
[item setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];
// 选中状态下的文字属性
NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
selectedAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[item setTitleTextAttributes:normalAttrs forState:UIControlStateSelected];

3.3 UIAppearance

只要一个类遵守UIAppearance,就能获得全局的外观,UIview都可以获取所有的外观,我们可以获取所有的tabBarItem外观标识,但是,一般不用下面这种,因为下面这种方法获取的是全局的所有tabBarItem外观标识,我们在开发时,一般都是自己负责自己开发的部分,所以推荐使用下面第二种方法,只获取当前类的tabBarItem外观标识。

//获取全局的tabBarItem外观标识
UITabBarItem *item = [UITabBarItem appearance];
//获取当前这个类下面的所有tabBarItem
UITabBarItem *item = [UITabBarItem appearanceWhenContainedIn:self, nil]

appearance使用注意:一定要在控件显示之前设置才有用,一般会放在+ (void)load方法中而不放在+(void)initialize中,因为+ (void)load方法只会调用一次,+(void)initialize可能会调用多次,使用时还需要判断。

load方法:加载类的时候调用,类在什么时候加载呢?程序一起动就调用load方法 Initialize方法:初始化类,当第一次使用这个类或者子类的时候调用 viewdidload方法:当viewcontroller第一次即将显示的时候加载。viewController都是懒加载,即都是在即将显示出来时才加载viewdidLoad,但是只有 tabbarcontroller是在一创建控制器的时候就进行加载viewdidLoad。

四 pch文件的定义

PCH文件(Precompile Prefix Header File),也就是预编译头文件,其作用就是,方便你一次性导入在多个文件中同时用到的头文件、宏或者URL地址等(全局使用),可以有效的帮你节约时间,提高开发效率。但是,自从Xcode 5之后,这个文件默认就不再提供了,如果你还想继续使用的话,需要手动创建并配置。至于为什么默认不再提供,可能是出于提高编译效率方面的考虑,毕竟预编译也会提高Build的时间。

具体如何创建和配置PCH文件详情可以参见:ios中pch文件的创建与配置

下面是在编写PCH文件需要注意的一些情况:

#ifndef PrefixHeader_pch
#define PrefixHeader_pch
/*** 如果希望某些内容能拷贝到任何源代码文件(OC\C\C++等), 那么就不要写在#ifdef __OBJC__和#endif之间 ***/
/***** 在#ifdef __OBJC__和#endif之间的内容, 只会拷贝到OC源代码文件中, 不会拷贝到其他语言的源代码文件中 *****/
#ifdef __OBJC__
#endif
/***** 在#ifdef __OBJC__和#endif之间的内容, 只会拷贝到OC源代码文件中, 不会拷贝到其他语言的源代码文件中 *****/
#endif

五 在Build Setting中配置宏

宏定义除了在类中用#define进行定义之外,在iOS开发过程中,我们还可以通过在Build Setting中进行配置宏,而在Build Setting中定义的宏在项目中会找不到,就是我们通过【command】+【鼠标单击】会显示一个【?】,无法跳到对应定义的位置,这时候可能就是配置在Build Setting中,例如我们经常见到的宏 DEBUG 就配置在配置在Build Setting中。

注意点:Build Setting中配置的宏的名字不能全部是小写字母,如果宏的名字全部是小写, 会出现以下错误

(0)

相关推荐

  • 详解iOS项目基本框架搭建

    项目开发过程中,在完成iOS项目--项目开发环境搭建之后,我们首先需要考虑的就是我们的项目的整体框架与导航架构设计,然后在这个基础上考虑功能模块的完成. 一 导航架构设计 一款App的导航架构设计应该是符合人们的操作惯性和方便操作的特点,也应该在交互上更加合理和人性化.根据项目功能和定位不同,不同的App的导航设计应该采用不同的技术框架,目前比较常见的导航框架主要有标签式.列表式.矩阵式三大类,如下图. 目前资讯新闻类的移动端项目的主流App框架基本都是标签式的,这种类型的导航设计技术上基本上都

  • 详解vue-cli项目中用json-sever搭建mock服务器

    vue-cli下配置json-server 使用json-server实现后台数据接口 先建一个json文件:db.json 放在build/下 在build/dev-server.js中配置 (注意变量命名) github说明: 启动项目 地址栏输入 localhost:8081 服务已启动成功 8081后加相应后缀即可访问数据 localhost:8081/posts l localhost:8081/comments 最后做一下浏览器代理 设置config/index.jsr如下 最后验证

  • 详解iOS自定义UITabBar与布局

    在小编整理过的文章iOS项目基本框架搭建中,我们详细说明了如何对TabBarItem的图片属性以及文字属性进行一些自定义配置.但是,很多时候,我们需要修改TabBarItem的图片和文字属性之外,还需要自定义TabBarItem的位置,这样系统自带的TabBar的样式并不能满足我们的项目需求,所以我们需要对系统的UITabBar进行自定义,以达到我们的项目需求.例如新浪微博App的底部tab的item就无法用自带的TabBarItem进行实现,最中间那个[+]发布微博并不是用来切换tab的,而是

  • 详解IOS判断当前网络状态的三种方法

    在项目中,为了好的用户体验,有些场景必须线判断网络状态,然后才能决定该干嘛.比如视频播放,需要线判断是Wifi还是4G,Wifi直接播放,4G先提示用户.获取网络状态的方法大概有三种: 1. Reachability 这是苹果的官方演示demo中使用到的方法,我们可以到苹果官方文档里下载Demo(点击左上角Download Sample Code 即可下载),然后把Demo里的Reachability.h和.m考到自己项目中,并在Build Phases 的 Link Binary 添加Syst

  • 详解IOS如何防止抓包

    目录 抓包原理 防止抓包 一.发起请求之前判断是否存在代理,存在代理就直接返回,请求失败. 二.我们可以在请求配置中清空代理,让请求不走代理 SSL Pinning(AFN+SSL Pinning)推荐 扩展 抓包原理 其实原理很是简单:一般抓包都是通过代理服务来冒充你的服务器,客户端真正交互的是这个假冒的代理服务,这个假冒的服务再和我们真正的服务交互,这个代理就是一个中间者 ,我们所有的数据都会通过这个中间者,所以我们的数据就会被抓取.HTTPS 也同样会被这个中间者伪造的证书来获取我们加密的

  • 详解vue项目打包后通过百度的BAE发布到网上的流程

    经过两天的研究终于将VUE打包后的项目通过BAE发布到了网上.虽然接口方面还有一下问题但是自己还是很高兴的. 首先说一下这个项目需要用到的技术,vue+express+git+百度的应用引擎BAE. 继续编辑终于将自己写的JSON文件模拟的数据也传上去了. 具体的步骤: 1,首先讲写好的vue项目打包(具体的打包过程我就不在说了,直接npm run build,就会在VUE项目文件中重新创建一个dist文件,这个就是打包好的项目) 2,在百度的应用引擎BAE部署一个项目,一天才2毛钱很便宜.自己

  • 详解Python的爬虫框架 Scrapy

    网络爬虫,是在网上进行数据抓取的程序,使用它能够抓取特定网页的HTML数据.虽然我们利用一些库开发一个爬虫程序,但是使用框架可以大大提高效率,缩短开发时间.Scrapy是一个使用Python编写的,轻量级的,简单轻巧,并且使用起来非常的方便. 一.概述 下图显示了Scrapy的大体架构,其中包含了它的主要组件及系统的数据处理流程(绿色箭头所示).下面就来一个个解释每个组件的作用及数据的处理过程(注:图片来自互联网). 二.组件 1.Scrapy Engine(Scrapy引擎) Scrapy引擎

  • 详解Maven项目缺少Maven Dependencies解决方法总结

    一.今天搭建了一个maven项目,在pom.xml文件引入依赖后,发现项目结构中没有Maven Dependencies文件(下图),但是在java Build Path中又可以找到Maven Dependencies文件(如下图): 但是,pom.xml文件中添加的依赖jar包也不会自动下载到项目中,update Project也是一样,于是是网上查找了很多方法,尝试后都发现没有用,最终,查看自己的pom.xml文件,发现是在依赖前面写了<dependencyManagement>这个标签(

  • 详解iOS Method Swizzling使用陷阱

    在阅读团队一项目源码时,发现Method Swizzling的写法有些瑕疵.这篇文章主要就介绍iOS Method Swizzling的正确写法应该是什么样的. 下面是iOS Method Swizzling的一种实现: + (void)load { Class class = [self class]; SEL fromSelector = @selector(func); SEL toSelector = @selector(easeapi_func); Method fromMethod

  • 详解IOS WebRTC的实现原理

    概述 它在2011年5月开放了工程的源代码,在行业内得到了广泛的支持和应用,成为下一代视频通话的标准. WebRTC的音视频通信是基于P2P,那么什么是P2P呢? 它是点对点连接的英文缩写. P2P连接模式 一般我们传统的连接方式,都是以服务器为中介的模式: 类似http协议:客户端?服务端(当然这里服务端返回的箭头仅仅代表返回请求数据). 我们在进行即时通讯时,进行文字.图片.录音等传输的时候:客户端A?服务器?客户端B. 而点对点的连接恰恰数据通道一旦形成,中间是不经过服务端的,数据直接从一

随机推荐