1.⼯程⽬录说明
1.1. Common放公共代码,Pages放业务模块相关
image.png1.2. Manager全局管理类,每个管理类⼀个⽂件夹
1.3. Api放所有的请求接⼜及返回的数据模型,每个接⼜⼀个⽂件夹,如下:
image.png1.4. Base放置基础组件
⽬前有CassBaseView,CassBaseVC…
1.5. Category放置分类名
需要全局引⼊的,加⼊CassCategories.h,如下:
image.png
image.png
1.6. Macro放置全局的宏(全部宏以CS_开头,必须全⼤写)
image.pngCassMacro⾥import所有公共宏⽂件
CassColor公共颜⾊宏⽂件
CassConstants公共常量宏⽂件
CassThirdPart第三⽅平台的key,id等等
CassCacheKey,本地缓存key
CassNotification 通知name
1.7. Util⼯具类
1.8. Library ⼿动导⼊的第三⽅
image.png1.9. 公⽤模块
image.png注意:需要全局引⼊的,请在模块下的.h⾥引⼊,严禁放pch⾥
2.代码格式化
2.1.空格和空⾏的使⽤
2.1.1.运算符的两侧使⽤空格
所有的双⽬运算符,包括:加(+)、减(-)、乘(*)、除(/)、取余(%)、赋值
(=、+=、-=等)、⽐较运算符(>、<、==、!=等)、逻辑运算(&&、||)、
位运算符 (|、&、<<、>>)等的两侧都应该添加空格,⽰例如下:
image.png
?:运算符在?和:的两侧都应该添加空格,⽰例如下:
image.png
单⽬运算符(!、++、--)⽆需添加空格:
image.png
2.1.2.⽅法命中空格使⽤
⽅法名中“+”或“-”与⽅法返回类型之间应添加⼀个空格,⽅法中参数
类型和“*”之间应该添加
⼀个空格。多个⽅法的实现之间应该空⼀⾏。
image.png
⽅法定义时,左⼤括号可以和⽅法名在同⼀⾏,也可以单独占⽤⼀
⾏,和⽅法在同⼀⾏中时,左⼤括与⽅法的最后⼀个参数之间应该空
⼀格:
image.png
⽅法连续调⽤时,在中括号后添加空格。
image.png
2.1.3.属性定义时空格的使⽤
属性定义时,property关键字与左括号,右括号与属性类型,括号中
逗号之后,属性类型与 *之间都应该添加空格,⽰例如下:
image.png
属性定义时,⼩括号中各个部分的顺序约定如下:原⼦访问类型、读写权限、内存管理⽅式。
image.png
2.2.⾏数和列数的限制(不强制)
2.2.1.⼀个函数的长度不应该超过80⾏
当函数长度超过80⾏后,应该将内部⼀些复杂的逻辑提炼出来,形成
新的函数,然后调⽤ 之,微型重构⼯作也应该⽆处不在,⽽不是等
项⽬完成后再来重构。
2.2.2.每⾏代码长度建议不超过120
建议每⼀⾏代码的长度超过120字符时做折⾏处理,处理时请以结构
清晰为原则。通过 “Xcode => Preferences => TextEditing => 勾选Show
Page Guide / 输⼊100 => OK” 来设置提 醒
2.2.3.每个类原则上不超过600⾏
⼀个类不应该将很多复杂的逻辑揉合到⼀起来实现, 我们约定当.m
⽂件超过600⾏时,要考 虑将这个⽂件进⾏拆分,可以使⽤类⽬
(Category)的⽅法来分离功能代码。如果逻辑过于 复杂,则应该考虑
从设计上将⼀些内部可以独⽴的逻辑提炼出来,形成新的类,以减轻
单⼀ 类的复杂度。
2.3.⽅法的声明、定义和调⽤
2.3.1.⽅法的声明和定义
正常情况下,所有参数应在同⼀⾏中,当参数过长时,每个参数占⽤⼀⾏,以冒号对齐。如下:
image.png
如果⽅法名⽐参数名短,每个参数占⽤⼀⾏,⾄少缩进4个字符,且为垂
直对齐(⽽⾮使⽤冒号 对 齐)。如:
image.png
2.3.2.⽅法的调⽤
⽅法调⽤和⽅法声明规则⼀致,如下:
image.png
2.4.代码分段的使⽤
`由于Objective-C的源码⽂件通常会⽐较⼤,代码⾏较多,推荐使⽤#pragma mark XXX 将代 码不同的处理段分隔开,分段名称的⾸母⼤写,⽅便在编辑器中快速定位到需要查看的代 码。以下是⼀些建议:
2.4.1.Lifecycle分段
在UIViewController的⼦类实现⽂件中,建议添加⼀个#pragma mark -
life cycle分段,该分段包含,init、loadView、viewDidLoad、
viewWillAppear、viewDidAppear、 viewWillDisappear、
viewDidDisappear、viewWillLayoutSubviews、dealloc等⽅法,并建议
将dealloc⽅法放到实现⽂件最前⾯。
建议将Lifecycle分段放到.m⽂件的最前端,因为对⼀个类的阅读,往
往是从init、 viewDidLoad等⽅法开始的。⽰例:
image.png
2.4.2.代理分段
建议为每⼀个代理添加⼀个分段,并且分段的名称应该是代理名称,
代理名称务必正确拼 写,这样可以通过command+单击来查看代理的
定义,⽰例:
image.png
2.4.3.Property分段
每个类都会有属性,需要为属性添加⼀个分段,该分段包括属性的
get和set⽅法,属性⽅法 的初始化应尽量放到get⽅法中完成,⽽不应
该全部放到viewDidLoad或者UIView的init⽅法 中,这样会增加
viewDidLoad和init⽅法的复杂影响可读性。
另外建议将propery分段放置在.m⽂件的最后,因为该分段主要只包
含⼀些属性的初始⽅法 不需要太多查看,需要查看时可以直接
command+单击跳转到get⽅法查看。
image.png
2.4.4.Inherit分段
对从⽗类继承的⽅法,单独添加⼀个inherit分类,⽰例如下:
image.png
2.4.5.Events分段
为button的点击事件,geture的响应⽅法,KVO的回调,Notification的
回调⽅法添加⼀个 events分段,在该分段的⽅法中,调⽤对应业务的
⽅法,对应业务的⽅法放在对应业务的分 段。
image.png
2.4.6.Public分段
public段的⽅法,为需要暴露给其他类,供其他类调⽤的⽅法,根据
具体情况决定是否添加该分段。
image.png
2.4.7.Private分段
private段的⽅法,是为实现本类业务⽽添加的⽅法,不需要暴露接又
给其他类,只提供给本 类的⽅法调⽤。根据具体情况决定是否需要
添加该分段。
image.png
2.4.8.根据具体业务添加分段
在⼀个类中,为相对⽐较独⽴的业务,或者是实现相对独⽴功能的⽅
法进⾏分段,同⼀个类 中业务不宜过多,业务过多时就应该考虑分
拆该类了。⽰例:
image.png
2.4.9.分段建议
关于分段,往往会出现的问题是,⼀个⽅法既应该放在Private段,又
应该放在某个功能 或业务段,这种建议的处理⽅式如下:
如果⼀类中,所有的⽅法都可以很好的归到不同的功能、业务分段,则⽆需添加
Private段,将对应的⽅ 法放到各个业务段即可。
如果⼀个类⽐较简单就只有⼏个⽅法,则可以将对应⽅法全部放到Private分段,⽽
⽆ 需添加业务分段。
⼀个⽅法既能放在Public段,又属于某⼀个业务段时,可以采⽤如下
⽅法:
将⽅法归到其对应的业务段中,然后在Public业务段中重新定义⼀个⽅法,在该⽅
法中调⽤业务段中对应 业务功能的实现。
在UIViewController的实现⽂件中建议的分段及顺序如下图(根据情况
选择需要哪些分段, 不需要总是包含以下所有分段):
#pragma mark - Lifecycle
#pragma mark - Inherit(继承)
#pragma mark - Events
#pragma mark - Delegate //各个代码分类
#pragma mark - Public methods
#pragma mark - Private methods
#pragma mark - xxx //各个独立业务和独立功能的分段
#pragma mark - Properties
#pragma mark - 懒加载
3.命名规范
objective-c中所有命名,应以能够清晰表达其含义为第⼀标准,命名
长⼀点没关系,最主要
的就是清晰。
所有命名尽量使⽤英⽂,万不得已可以使⽤拼⾳。使⽤拼⾳时,类、
协议可以⽤拼⾳⾸字母
做前缀,如:TM;特卖,资源图⽚,变量等使⽤拼⾳时应⽤全拼,并写
上对应的注释。
3.1.变量属性命名
变量名应使⽤容易意会的应⽤全称,且⾸字母⼩写,且使⽤⾸字母⼤
写的形式分割单词。成 员变量使⽤“_”做为前缀,以便和临时变量与
属性区分,⽰例:
image.png
变量名称应直接体现出变量的类型,禁⽌让变量命名产⽣歧义或误
导,如将⼀个UIButton命 名为view,将⼀个NSArray命名为dic等,⽰
例:
image.png
3.2.类、协议命名
类的命名以前缀开始,如:Cass,除前缀外的第⼀单词⾸字母也需要⼤
写,多个单词以单词 ⾸字母⼤写进⾏分割。类的命名⾸先应保证表
达意思明确,能⼀眼看出这个类是做什么任务 的,然后才考虑名字
的长度(不要怕长)。
协议的命名和类基本相同,协议命名末尾⼀般加上单词delegate来表
⽰这是个代理协议的名 称,⼤部分情况下协议名可以直接在其相应
的类名的尾部加上Delegate即可,⽰例:
类名:AFHTTPRequestOperationManager,QMEmptyManager 协议
名:GADAppEventDelegate,GADBannerViewDelegate,
QMSegmentContainerDelegate
3.3.枚举的命名名
枚举类型的命名与类相似,以前缀开始,如:Cass,除前缀外的第⼀单
词⾸字母也需要⼤
写,多个单词以单词⾸字母⼤写进⾏分割。
枚举值的命名是在枚举类型之后加上表⽰该值的⼀个或多个单词,每
个单词⾸字母⼤写。⽰例如下:
image.png
枚举值的确定可以使⽤默认的数值,也可参照系统很多枚举的赋值,
采⽤移位的⽅法来赋值,这样做的好处在于,可以使⽤按位或和按位
与来进⾏逻辑判断和赋值,简化代码的编写。(不强制)
3.4.宏和常量的命名
宏的命名全部为⼤写,为了避免跟第三⽅的宏定义冲突,宏定义全部
以CS_开头,多个单词之间⽤下划线(_)分割。可以参考系统⾃带宏的
命名,命 名单词应该表达出该宏表⽰的是个什么值,⽰例:
image.png
常量的命名和变量基本⼀致,只是需要⽤⼩写字母k作为前缀,⾸字
母⼤写来分割单词。
image.png
注:常量和宏的定义放在当前⽂件的顶部,不要放在⽂件中间,以⽅
便查看。
NSNotification
当你定义你自己的 NSNotification 的时候你应该把你的通知的名字定义为一个字符串常量,就像你暴露给其他类的其他字符串常量一样。你应该在公开的接口文件中将其声明为 extern 的, 并且在对应的实现文件里面定义。
因为你在头文件中暴露了符号,所以你应该按照统一的命名空间前缀法则,用类名前缀作为这个通知名字的前缀。
同时,用一个 Did/Will 这样的动词以及用 "Notifications" 后缀来命名这个通知也是一个好的实践。
// Foo.h
extern NSString * const ZOCFooDidBecomeBarNotification
// Foo.m
NSString * const ZOCFooDidBecomeBarNotification = @"ZOCFooDidBecomeBarNotification";
3.5.⽅法函数命名
⽅法名的⾸字母⼩写,且以⾸字母⼤写的形式分割单词,⽅法名和参
数加起来应该尽可能的
像⼀句话,能够清晰的表达出这个⽅法所要完成的功能,⽰例:
image.png
3.6.扩展(category)命名
category的命名和类基本⼀致,以Cass为前缀,⾸字母⼤写,category
的命名应该体现 出该扩展主要功能。
image.png
注意: ⽅法命名规则以 cass_
3.7.⽂件夹⽬录命名规范(待定)
3.8.资源图⽚命名
login_cancel_selected, login_cancel_normal,
arrow_right_white(gray)
资源图⽚业务或者页⾯进⾏分组,每组建⼀个folder,其名称为对应
业务功能或页⾯名称, 所有⽂件夹以及图⽚的名称禁⽌使⽤中⽂,
只能使⽤英⽂字符。
资源图⽚的命名规则为:业务/页⾯图⽚名称状态。 业务/页⾯:为图
⽚所对应的业务或页⾯名称,⾸字母⼩写并以⾸字⼤写的形式分割多
个单 词;图⽚名称:为图⽚真实名称,⾸字母⼩写并以⾸字⼤写的形式
分割多个单词;
状态:主要包含三种:正常、按下、选中,分别⽤normal、pressed、
selected来标记,在没 有不同状态,即只有正常状态的情况下可以省
略状态这⼀栏,⽰例:
➢ 在navigationBar上的菜单按钮图标和返回按钮图标可以分别命名如
下: nav_menu_normal nav_menu_selected
➢ 没有消息,没有订单时空态页⾯上显⽰的图⽚,可以统⼀定为“空 态”这个业务,且这些 图⽚没有多种状态,故可以省略状态⼀栏:
empty_message empty_order
➢ 登陆时输⼊框的背景图⽚可以命名为: login_boxBackground
4.注释
4.1.注释的格式
在头⽂件,即.h⽂件中添加的注释,包括类、属性、⽅法等的注释应
该使⽤xcode的标准⽅ 式,这样可以⽅便在别的⽂件中使⽤到该类或
其属性或⽅法时,可以通过option+单击快速 查看其注释。
标准注释格式可以由xcode的插件直接⽣成,对于⽐较简短的注释,
建议直接⽤如下格式,, 会更加简洁:
/** 注释内容 */,如:
image.png
4.2.类的注释
在每个类的头⽂件的顶部,添加注释,简单的说明这个类是完成什么功能的,如果在新的版
本开发对类进⾏⽐较重要的修改,也应该简单的注释下在哪个版本做了哪些修改,便于以后
维护代码时能够更多的定位问题:
image.png
4.3.属性和⽅法的注释
对暴露在头⽂件中的属性和⽅法进⾏注释,以告诉以便在调⽤这些属
性和⽅法进⾏查看:
image.png
4.4.⼀些必要的注释
对于⼀些逻辑⽐较复杂的代码,应该添加必要的注释,⽅便⾃⼰和他
⼈以后维护代码,⽰例:
image.png
对于枚举类型的每⼀个枚举值应该给出注释:
image.png
5.注意
5.1.不要在dealloc⽅法和init⽅法中调⽤属性
不要在dealloc和init⽅法中使⽤属性,即不要使⽤self.name这样的⽅
式,⽽应该使⽤ _name。理由可以参考:http://blog.devtang.com/blog/
2011/08/10/do-not-use-accessor-in- init-and-dealloc-method
5.2.NSString类型的属性声明为copy
假设将A中的⼀个MutableString给B中的⼀个Property(NSString类型)赋
值,⾸先是能接受 的,⽗类可以接受⼦类,如果是retain,仅仅是⽣
成⼀个指针,计数器加⼀,然后指向那个 MutableString。如果
MString改变,B中那个跟着改变,因为是同⼀块内存区域。⽽选择
Copy相当于又⽣成了⼀个NSString,与A中的MutableString独⽴。
5.3. UITableView代理在dealloc中将delegate置为nil
虽然⽬前已使⽤ARC管理内存,但是仍然需要在dealloc⽅法中将
UITableView, UIWebView,UICollectionView等类型实例的
delegate,dataSource置为nil。因为这些属性使⽤ 的是assign⽽不是
weak,所以在其指向的对象被释放时,它们不会⾃动置为nil。
5.4.提前释放NSTimer对象
会循环使⽤的Timer(指定了repeat参数为YES),必须要在合适的时机
调⽤invalidate⽅ 法,否则会出现内存泄漏,在使⽤类的析构函数中
调⽤Timer的invalidate⽅法为时已晚,因为timer会对其传递的⽬标
object增加引⽤计数,若不调⽤invalidate,使⽤类根本得不到析构。
加runloop
5.5.头⽂件暴露最少的接⼜
头⽂件中应该暴露最少的接⼜,只将真正需要供其他类调⽤的⽅法和
属性暴露在头⽂件中。
5.6.只引⼊需要的头⽂件
在每个⽂件中应该引⽤尽量少的头⽂件,不要引⼊⽤不到的类,也不
要重复引⽤头⽂件,当⽂件有修改时记得查看是否有已不再不需要引
⽤的头⽂件,及时移除。
5.7.NSNotiIication的注册与卸载
NSNotification的注册应该放到init⽅法中,为了监听到所有通知,应
该将注册通知的时机尽
量提前,⽽init⽅法是可以注册通知的最早时间点。 在对象被释放
时,应该取消其监听的所有通知,所有应该在dealloc⽅法中调⽤
[[NSNotificationCenter defaultCenter] removeObserver:self]等⽅法来卸
载通知。
5.8.⽤枚举替换数字
对于商品状态,⽹络请求错误类型,UIView及其⼦类的tag等,由不
同数值进⾏区分的情 况,⼀律使⽤枚举,不允许直接使⽤数字进⾏
编码。
5.9.switch/case的使⽤
每⼀个case必须有⼀个break,如果的确有特殊业务需求不需要break
的,需要明确的注释说明;必须要有⼀个default分⽀,哪怕default分⽀
什么也不做,也要写上break;每⼀个分⽀ 都⽤⼤括号括起来。
image.png
5.10.调⽤super⽅法
在⾃定义以下⽅法时,必须调⽤其super⽅法: UIViewController相关⽅
法:
viewDidLoad、viewWillAppear、viewDidAppear、
viewWillDisappear、 viewDidDisappear、viewWillLayoutSubviews、
viewDidLayoutSubviews等。
UIView相关⽅法:layoutSubviews UITableViewCell/
UICollectionViewCell相关⽅法:prepareForReuse
网友评论