Skip to main content

代码规范

为了使代码清晰简洁、方便阅读理解,一套良好的编码规范尤为重要。尤其是在多人协作时,我们不仅要去看别人的代码,也要让别人看我的代码。维持风格统一,可以有效节约沟通成本,使工程更可维护,使产品可持续发展。

这其中最核心的原则就是提高代码可读性。

代码的排版格式#

方法集注释:#pragma mark#

统一工程中的代码排版顺序,做到工程内代码整齐、风格统一,利于维护。使用方法集对代码进行分区,对功能相近的方法归类整理,方便函数查找,理解代码结构,从而准确排查问题,节约开发时间。

以控制器的排版格式为例:

#import xxx
// 头文件导入
#define xxx
// 宏定义
@property (nonatomic,strong) xxx
// 属性声明
#pragma mark – life cycle
// 控制器生命周期,从创建到销毁的顺序进行按需编写。
#pragma mark - overwrite
// 父类方法重载
#pragma mark – initUI
// 初始化UI
#pragma mark – initData
// 初始化数据
#pragma mark – delegate
// 代理方法
#pragma mark – target method
// 页面事件及通知
#pragma mark – getters and setters
// get\set方法(懒加载)
#pragma mark – private method
// 私有方法

这些逻辑区块不仅仅使得阅读代码本身容易许多,也为Xcode源导航增加了视觉线索。当你点击功能栏的方法那一区块的时候就会出现以下的列表。

ps:使用 #pragma mark可以增加一行水平分割线,如下图:

iOS代码编码规范#

  1. 可读性第一原则。书写代码时,代码的可读性大于代码的简洁性。可读性第一,不要盲目追求代码的简洁,在团队协作中可读性好的代码才有更好的可维护性,而且一般情况下也具有更好的健壮性。代码的语法运用与书写顺序应以可读性优先。

  2. 函数长度不要超过50行,小函数的可读性要比大函数强,当超过50行时就要考虑是否需要对函数进行拆分以增强函数的可读性。 为了使代码更加紧凑可读,任意行的代码不能超过80字符。

  3. 注释有很多好处,方便自己日后阅读代码,方便他人阅读自己代码,从而降低后期维护成本。虽然优秀的代码大多数是可以自描述的,完全可以通过程序代码本身来表达它到底在做什么,但以下情况应写明注释:

    • 主要部分的头文件注释说明这个类的用途

      // 包含第三方 和 应用内业务的实现,减轻入口代码压力
      @interface AppDelegate (AppService)
      - (void)initWindow;
      - (void)initThirdPartyConfig;
      - (void)initAppStatusMonitor;
      - (void)initUserData;
      @end
    • 涉及专业知识或复杂逻辑,此时要说明实现原理及思路。

  4. 变量、宏、类型常量、方法、类的命名做到自描述、精准表达含义,因此应做到用词准确同时完整拼写。

    变量名必须使用小驼峰格式,包含名称与类型。

    正例:UILable *nameLb;
    反例:UILable *name; 没有说明变量类型,表达模糊

    宏使用大写字母并用下划线“_”分割。

    #define URL_LOGIN @“/singIn”

    类型常量使用"k"作为前缀,大驼峰方式进行命名。

    NSString * const kUserNameLocalKey = "userNameLocalKey"

    方法名语义连贯使用小驼峰格式。

    正例:sortStudents:byAgeAsc:
    反例:sort:byAge: 给什么排序?“byAge”如何排序?升序还是降序?

    类的名称使用大驼峰命名法,包含子类的用途及父类名称,如下:

    // 父类
    ListViewController
    // 子类
    StudentListViewController
    TeacherListViewController
  5. 避免全局常量的命名冲突,重复赋值的问题,在定义全局常量时使用类型常量来定义常量,而不是宏。 使用const进行修饰,保证唯一性及不可变性。

    正例: NSString * const kUserNameLocalKey = "userNameLocalKey"
    反例: const NSString * kUserNameLocalKey = "userNameLocalKey" const修饰*kUserNameLocalKey,值可以被改变
  6. 因为预处理命令是在与处理器中进行文本替换,相当于代码的拷贝粘贴,因此定义函数宏时表达式及变量使用小括号包围,维持运算的优先级,避免莫名其妙的问题。

    #define NUM_MAX(A,B) ((A)>(B)?(A):(B))
  7. 一个函数只做一件事情,每个函数的职责明确划分,保持逻辑清晰。

    正例:createUI(); getData();

    反例:createUI() {getData()}

  1. Block

    block捕获变量、代码传递、代码内联等特性赋予了它多于代理机制的功能和灵活性。 为常用的block类型创建typedef。 通过typedef声明重复使用的代码块,这样在后续增加或修改参数时只需修改定义的代码就好了。

    typedef void (^NetCallBack)(Bool isSuccss, NSDictionary *errorInfo,NSDictionary *result)
    NetCallBack block = ^( Bool isSuccss, NSDictionary *errorInfo,NSDictionary *result){
    }
  2. 应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。

    正例;
    ```c
    typedef NS_OPTIONS(NSUInteger, UserLoginStatus) {
    UserLoginStatusOnline = 0,
    UserLoginStatusOffLine,
    UserLoginStatusInvisible
    };
    switch(loginStatus){
    case UserLoginStatusOnline:
    {
    //在线
    }
    break;
    case UserLoginStatusOffLine:
    {
    //离线
    }
    break;
    case UserLoginStatusInvisible:
    {
    //隐身
    }
    break;
    }
    ```
    反例:
    ```c
    if (loginStatus == 0){
    // 正常在线
    }else if(loginStatus == 1){
    // 离线
    }else if(loginStatus == 2){
    // 隐身
    }
    ```

    在处理枚举类型的 switch 语句中不要实现 default 分支。这样加入新的枚举值之后,编译器就会发出警告提示。

使用缩写#

系统常用类的变量后缀缩写:#

缩写
UIViewControllervc
UIViewview
UILabellb
UIButtonbtn
NSArrayarr
NSDictionarydic
NSMutableArraymarr
NSMutableDictionarymdic
NSStringstr
NSMutableStringnsr

用单词缩写#

全拼缩写
Applicationapp
Informationinfo
Initializeinit
Minimummin
Messagemsg
Temporarytemp
Notificationnoti

专有名词的缩写#

一些特殊的专有名词我们可以直接拿来使用比如:HTML、URL、GIF、PNG等。