[关闭]
@FoxBabe 2015-04-07T23:28:06.000000Z 字数 7250 阅读 3036

Objective-C 代码规范


1 文档目的和使用范围

1.1 文档目的

本文档目的在于定义iOS开发过程中的编码规范,统一编程风格,提高代码的可读性与团队编码效率,避免团队开发可能造成的混乱。

1.2 使用范围

本文档规范使用于团队内使用Objective-C开发的工程项目。

2 编码规范

2.1 项目工程框架布局

工程目录框架

QQ20150401-1.png

说明:

  1. * Resource存放资源文件,图片、字体和配置文件等;
  2. * Macro宏定义目录,存放程序的常用宏定义和第三方参数的宏定义;
  3. * Helper常用帮助工具汇总;
  4. * Categroy常用类的扩展文件;
  5. * NetWork网络框架工具
  6. * UI常用公共控件
  7. * Depends第三依赖库文件夹
  8. * Models模型对象
  9. * Views项目中自定义的视图和控件
  10. * Controllers项目中的控制器,根据实际业务再进行分组

头文件和实现文件的代码布局顺序

头文件布局优先顺序,从上到下递减

  1. * .h头文件描述,描述参考注释模块
  2. * 引用的头文件
  3. * 常量定义和宏定义,如常用的通知、常量和公用宏的定义
  4. * 类和协议说明,使用@class@protocol来说明某个类型为类或协议
  5. * 类定义,即定义@interface和其成员变量
  6. * 类属性,在@interface外定义类的属性
  7. * 类方法和实例方法
  8. * 协议定义
  9. * 扩展类别

实现文件布局优先顺序,从上到下递减

  1. * .m实现文件描述,描述参考注释模块
  2. * 引用的头文件
  3. * 常量定义的实现
  4. * 内存管理,目前采用ARC编码,这里的内存指在dealloc文件中移除通知,清空特殊数据等,此步可选。
  5. * 数据初始化和界面初始化
  6. * 详情实现方法,使用#parma mark Detail methods来分组
  7. * 其他归类方法的分组
  8. * 自定义类的协议实现方法,按照不同的协议分组显示
  9. * 系统类的协议实现方法,按照不同的协议分组显示
  10. * 扩展类别的实现方法

实现文件中,务必定义初始化方法,变量在使用之前,都必须统一进行初始化赋值;对于设计界面的类,如集成View或ViewControler,需要添加界面初始化的方法。

2.2 命名规范

基本原则

  1. #!objective-c
  2. extern ushort APIDefaultPageSize; // 还行,能明白意思了
  3. extern ushort APIDefaultFetchPageSize; // 加上些限定更好一些
  4. extern ushort APIFetchPageSizeDefault; // 再好些,把重要的往前放
  5. YHToolbarComment // 不推荐
  6. YHCommentToolbar // OK,把类型(toolbar)置后

资源文件命名

缩写 含义
btn 按钮
hlbtn 按钮的高亮
bg 背景图片
hlbg 背景图片的高亮
img 图片
icon 图标
  1. #!objective-c
  2. personalcenter_edituserinfo_btn //个人中心编辑用户信息按钮
  3. common_save_btn //共用的保存按钮

类名

方法命名

例如:

  1. #!objective-c
  2. // OK
  3. - (NSString *)name;
  4. // 糟糕,应用上面的写法
  5. - (NSString *)getName;
  6. // OK,但极少使用
  7. - (void)getName:(NSString **)buffer range:(NSRange)inRange;
  8. // OK
  9. - (NSSize)cellSize;
  10. // 糟糕,应用上面的写法
  11. - (NSSize)calcCellSize;
  12. // 对 controller 做一般设置,OK
  13. - (void)setupController;
  14. // 列出具体设置的内容,更好
  15. - (void)setupControllerObservers;
  16. // 糟糕,set 专用于设置属性
  17. - (void)setController;

协议命名

通知命名

  1. #!objective-c
  2. NSApplicationDidBecomeActiveNotification
  3. NSWindowDidMiniaturizeNotification
  4. NSTextViewDidChangeSelectionNotification

变量命名

  1. #!objective-c
  2. UILabel *userNameLabel
  3. UIButton *loginBtn

常量命名

  1. #!objective-c
  2. #define PI 3.1415926

除以上规则约定外,其他常量约定了以下前缀:

前缀 含义
k 宏常量
CDEN CoreData entity name
UDK User Default Key

大小写规则

其他

缩写 含义
URL 链接地址
x 坐标
y 坐标
w 宽度width
h 高度height
vc 控制器ViewController
v 视图View
dic 字典Dictionary

2.3 编程规范

基本规范

  1. #!objective-c
  2. - (void)doSomethingWith:(GTMFoo *)theFoo rect:(NSRect)theRect
  3. interval:(float)theInterval {
  4. }
  5. - (void)short:(GTMFoo *)theFoo longKeyword:(NSRect)theRect
  6. evenLongerKeyword:(float)theInterval {
  7. }
  1. #!objective-c
  2. //OK
  3. [myObject doFooWith:arg1 name:arg2 error:arg3];
  4. [myObject doFooWith:arg1
  5. name:arg2
  6. error:arg3];
  7. //糟糕
  8. [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg
  9. error:arg3];
  10. [myObject doFooWith:arg1
  11. name:arg2 error:arg3];
  12. [myObject doFooWith:arg1

空格和空行

  1. #!objective-c
  2. // 糟糕
  3. -(void)methodName:(NSString *)string;
  4. // OK
  5. - (void)methodName:(NSString *)string;
  6. // 糟糕
  7. if ( a < b ) {
  8. // something
  9. }
  10. // OK
  11. if (a < b) {
  12. // something
  13. }
  14. // OK
  15. (someValue > 100)? YES : NO

花括号

  1. #!objective-c
  2. - (void)methodName:(NSString *)string {
  3. ↑空格 ↑空格,推荐花括号在一行
  4. if () {
  5. 空格↑ ↑空格,花括号不要另起一行
  6. }
  7. else {
  8. 要换行↑ ↑空格,花括号不要另起一行
  9. }
  10. }
  1. 说明:
  2. Xcode 默认的花括号位置是这样的:方法内部的各种补全都是在同一行的;方法定义的比较混乱,默认模版另起一行,但从 Interface Builder 中连线生成的方法在同一行的。
  3. 考虑到 Xcode 的默认行为,方法内部要另起一行,方法所在行不强制定死。另外,模版可以定制,而 IB 生成的代码不可定制,所以不另起一行的写法优先。
  4. 另起一行的写法在代码折叠后非常难看。

换行

长表达式(超过100列)要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐。
Google的80字符的标准有点少,这导致过于频繁的换行(Objectve-C的代码一般都很长)通过 “Xcode => Preferences => TextEditing => 勾选Show Page Guide / 输入100 => OK” 来设置提醒
函数(方法)声明时,类型与名称不允许分行书写。

  1. #!objective-c
  2. //OK
  3. extern double FAR CalcArea(double dWidth, double dHeight);
  4. //糟糕
  5. extern double FAR
  6. CalcArea(double dWidth, double dHeight);

枚举

  1. #!objective-c
  2. typedef enum
  3. {
  4. SDWebImageRetryFailed = 1 << 0, //无法下载时,列入黑名单中后,将不会再重新下载
  5. SDWebImageLowPriority = 1 << 1, //默认情况下,图像下载期间用户界面相互作用开始,这标志禁用此功能,
  6. SDWebImageCacheMemoryOnly = 1 << 2, //禁止磁盘缓存
  7. SDWebImageProgressiveDownload = 1 << 3 //这个标志使渐进式下载,图像显示逐步在下载期间作为一个浏览器会做的。
  8. } SDWebImageOptions;
  1. #!objective-c
  2. typedef NS_ENUM(NSInteger, TTITextAlignment) {
  3. TTITextAlignmentLeft = 0, // 左对齐
  4. TTITextAlignmentRight = 1, // 右对齐
  5. TTITextAlignmentCenter = 2, // 居中
  6. }

参考苹果最新的API头文件,推荐采用第二种来进行定义。关于枚举类型的命名和对应只命名作如下约定。

  1. 枚举类型命名规则:[类名]+[功能描述,如Type/Mode/Option]
  2. 枚举值命名规则:[类名]+[值的意思]

Block定义

项目中常见block定义方式,如下所示:

  1. #!objective-c
  2. typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType);
  3. typedef void(^SDWebImageDownloaderProgressBlock)(NSUInteger receivedSize, long long expectedSize);

block类型命名规则约定:[类名]+[状态](可选 + [条件描述,如withxxx])+ Block。

import VS include

使用#import引入Ojbective-C和Ojbective-C++头文件,使用#include引入C和C++头文件。

TODO/FIXME/!!!/???

程序编码过程中,我们可以通过一些标注,来提示自己有些事情是需要以后来处理的,为了防止遗漏,加上TODO、FIXME、!!!、???和waring是很有必要的,我们可以通过下面的方式添加对应的提醒:

  1. #!objective-c
  2. // TODO: 处理异常情况
  3. // FIXME: 此处需要清楚缓存
  4. // !!!: 此处逻辑不严谨,待完善
  5. // ???: 这块的实现上还存在难度,待研究跟进
  6. #warning 此处在特定情况下会出现异常,提交版本前一定要处理

前四种为备注说明,并且在预览方法时会清晰显示出来,后面warnning,是在编译程序后都会直接作为一个警告出现在编译结果中。

在实际开发中,如果开发到中途,要需要处理的,务必加上对应的标志,防止再次来编辑时遗漏。另外,在提交版本前,一定要对这些标志进行一次检查,warnning能很明显的发现,其他四种可以采用插件Xcode插件XToDo(https://github.com/trawor/XToDo)来查找。

其他

2.4 注释

头文件说明示例:

  1. #!objective-c
  2. //
  3. // TTiRecordStatueBar.h
  4. // CustomStatueBar
  5. //
  6. // Created by Fox on 14-7-16.
  7. // Copyright (c) 2014年 翔傲信息科技(上海)有限公司. All rights reserved.

注意:
* 个人创建的类必须修改为当前用户
* 版权同意为:翔傲信息科技(上海)有限公司
1. 方法注释只需要在申请方法的地方添加,实现时不需要添加;
2. 注释使用中文;

3 参考

本文档编写过程中参考了如下编码规范文档:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注