iOS

Objective-C 编码规范

Objective-C 编码规范

Posted by 你看那朵乌云儿 on February 23, 2017

从某种意义上来说, 我们写代码, 要让自己和别人更好地 Copy.
良好的编程习惯是必要的. 严格遵循优秀的编码规范, 能够很大程度地提高开发效率, 不用浪费实践去纠结一些细枝末节的东西.
该规范主要参考了 Apple API 设计风格和禅与 Objective-C 编程艺术 , 以及一些个人学习经验的总结.

命名规范

基本原则

  • 尽可能与 Cocoa 编程风格保持一致
  • 越重要, 区别度越大的语素越要往前放
  • 命名应该尽可能的清晰和简洁
  • 整个工程的命名风格要保持一致性, 不同类中完成相似功能的方法应该叫相似的名字

类名

  • 类的前缀, 所有类名最好都加一个统一的标示符, 可以是公司, 组织缩写, 或者项目的名称缩写
  • 类的后缀, 所有的试图控制器都加上 ViewController, 自定义容器控制器加上 Container, 所有的通知名都加上 Notification

方法名

  • 以 alloc, copy, init, mutableCopy, new 开头的方法要注意, 它们会改变 ARC 的行为, 不要使用
  • 以 get, set 开头的方法有特殊的意义, 不要随意定义. set 是属性默认的设置方法, 如果函数不是为了设置类成员, 则不要用 set 开头, 可用 setup 替代. get 在 Objective-C 中通常只用来表示从函数指针返回值的函数
  • 不要用 and 来连接两个参数

协议名

  • 好的协议名应能立刻让人分辨出这不是一个类名, 除了以常用的 delegate, dateSource 做结尾外, 还可以使用 …ing 这种形式, 如: NSCoding, NSCopying, NSLocking

通知名

  • 基本命名格式是: [与通知相关的类名] + [Did | Will] + [UniquePartOfName] + Notification
    比如: kUserInfoDidUpdateNotification
  • 另外, 尽量不要使用通知, 它可能会让你的代码难以维护, 当你想要使用的通知的时候, 你应当足够地评估它的必要性

临时变量命名

  • 临时变量可以写得很短, 如 tmp, k, vc 这样, 也可以加适当前缀

常量命名

  • 宏常量加 k 前缀
  • 建议使用 NS_ENUM 和 NS_OPTIONS 宏来定义枚举类型
  • 除非调试用的, 控制不同编译模式行为的常量可用宏外, 其他常量尽量不用宏定义

代码格式化

空格

  • 使用4个空格代替制表符
  • 方法声明在方法类型与返回类型之间要有空格
  • 方法返回值, 参数, 变量定义和声明, 指针符号 * 前面要有空格

      - (UIImage *)imageWithColor:(UIColor *)color;
    
  • 条件判断的括号内侧不应有空格
  • 关系运算符 (如 >=, !=) 和逻辑运算符 (如 &&,   ) 两边要有空格
      if(age > 14 && (gender == famale)) {
          [self doSonmething];
      }
    
  • 属性定义, 数组定义等逗号后留一个空格

      NSArray *numbers = @[@1, @2, @3];
    
  • 左花括号前要有空格
  • 注释中中英文之间要有空格

花括号

  • 方法, if, else, switch 的左花括号不换行
  • 右花括号单独一行
  • if, else 代码块只有一行代码花括号不省略

折行

  • 与多数其他规范不同, 不建议按照80限制手动折行, 太长可手动折行

字面值语法

  • 应该使用可读性更好的字面值语法来构造 NSArray, NSDictionary 等数据结构

      NSMutableArray *members = @[].mutablecopy;
    
  • 避免使用 Format

      NSLog(@"点击了第 %@ 行", @(indexPath.row))
    

布局

  • 采用纯代码布局, 动态布局使用 Masonry
  • 自定义 View, 不要在 ViewController 中有大量组装 View 的代码, 可以自定义 View, 然后将相关的事件响应用代理用着 block 传递给 Controller
  • 不可以在 layoutSubviews 中使用 autolayout
  • 每一个自定义 View 有一个 build 方法, 在 build 方法中完成子视图的创建, 不要在 init 方法中直接初始化和构建子视图

代码组织

  • 不要在 viewDidLoad 里面初始化 View 然后再 add, 可以使用懒加载或者为每一个 View 构造一个 build 方法
  • 注意提取通用 View 和自定义 View 的封装, 以减少 ViewController 中 View 的初始化
  • 使用 #pragma mark 将代码分成不同的块

      #Pragma mark - Life
      #Pragma mark - Getters & Setters
    
  • 提取工具方法, 若对应于某 Foundation 类, 建议添加到分类中, 分类方法建议加前缀
  • ViewController 中不应该有业务逻辑相关的方法
  • ViewController 应该是独立的, 它不需要知道其他 ViewController 的视图层级或者内部实现
  • ViewController 之间的通信必须定义明确的公共接口, 比如 Protocol
  • 建议不要重用 ViewController

单例

  • 如果可能, 请尽量避免使用单例而是依赖注入
  • 尝试着把单例作为一个对象的容器, 在代码或者应用层面上共享, 是一个糟糕和丑陋的设计

注释

  • 重要接口或属性可以添加注释
  • 推荐使用文档注释

      /**
       简要描述
      */
    
  • 修改了实现影响到接口的使用的, 一定要修改注释
  • 不要出现被注释掉的代码, 如果是出于特殊原因的, 一定要为这些代码添加注释

接口定义

  • 接口尽可能精简
  • 接口中不要使用可变数据类型

属性

  • 尽管使用实例变量是一种有效的方式, 但更偏向于使用属性来保持代码一致性
  • 除非必要, 否则不要手动合成属性
  • 在 init 和 dealloc 中不要用存取方法访问实例变量
  • NSString, NSArray 等有可变类型的数据类型需要使用 copy 语义
  • 统一空格和语义等的顺序, 比如:

      @property (nonatomic, readwrite, copy) NSString *title;
    

其他编码风格

  • 不要使用 new 方法
  • BOOL 的使用, 永远不要将 BOOL 类型变量直接和 YES 比较
  • nil 检查, 不要使用 nil == Object
  • 尽量不使用 PCH 文件