头文件

  1. @import AVFoundation; # 标准组件库库头文件,一般为苹果sdk自带的 framework
  2. #import DKViewController.h # 非标准库头文件
  3. 全局宏
  4. 常量定义
  5. 全局变量
  6. 类定义

切记不要 #import ,在 iOS7 以后推荐用 @import module;来引用苹果的组件。

例子

  1. @import AVFoundation;
  2. #import "Test.h"
  3. #define KTest 0
  4. static CGFloat const kALAnimationDelay = 0.1;
  5. static NSString *ID = @"cell";
  6. @interface MyClass ()
  7. @property (nonatomic) NSObject *test;
  8. @end

类结构

使用 #pragma mark – xxx 来分类方法

  1. #pragma mark Getters and Setters # 懒加载
  2. #pragma mark - Life Cycle # 实例生命周期
  3. #pragma mark - Events # 事件
  4. #pragma mark - Public Methods # .h 公开方法
  5. #pragma mark - UITableViewDataSource # 系统代理方法
  6. #pragma mark - UITableViewDelegate
  7. #pragma mark - UITextFieldDelegate
  8. #pragma mark - Custom Delegates # 自定义代理
  9. (#pragma mark Private Methods # 私有方法)

Private Methods

正常情况下 ViewController 里面不应该写,能抽掉尽量抽掉

  • 不是 delegate 方法的,也不是 event response 方法的,也不是 life cycle 方法的,就是 private method。
  • 正常情况下 ViewController 里面是不会存在 private methods 的,这个 private methods 一般是用于日期换算、图片裁剪等的小功能。这种小功能要么把它写成一个 category,要么把它做成一个模块,哪怕这个模块只有一个函数也行。
  • ViewController 基本上是大部分业务的载体,本身代码已经相当复杂,所以跟业务关联不大的东西,能不放在 ViewController 里面就不要放。另外一点,这个 private method 的功能这时候只是你用得到,但是将来说不定别的地方也会用到,一开始就独立出来,有利于将来的代码复用。

懒加载

很多开发工程师,初始化属性的位置比较随意,有单独添加一个初始化方法类似 setupView 的,有在 init 初始化的,各种情况都有,导致团队协作的时候代码显得非常乱。
初始化方式不一致,这样做非常有可能破坏了每个方法功能的单一性(每个方法只做一件事)。

  1. @interface CustomObject ()
  2. @property (nonatomic, strong) UILabel *label;
  3. @end
  4. @implementation
  5. #pragma mark - getters and setters
  6. - (UILabel *)label
  7. {
  8. if (_label == nil) {
  9. _label = [[UILabel alloc] init];
  10. _label.text = @"1234";
  11. _label.font = [UIFont systemFontOfSize:12];
  12. ... ...
  13. }
  14. return _label;
  15. }
  16. @end
  17. #pragma mark - life cycle
  18. - (void)viewDidLoad
  19. {
  20. [super viewDidLoad];
  21. [self.view addSubview:self.label];
  22. }
  23. - (void)viewWillAppear:(BOOL)animated
  24. {
  25. [super viewWillAppear:animated];
  26. self.label.frame = CGRectMake(1, 2, 3, 4);
  27. }

空格

使用空格而不是制表符 Tab
不要在工程里使用 Tab 键,使用空格来进行缩进。在 Xcode > Preferences > Text Editing 将 Tab 和自动缩进都设置为 4 个空格。(Google 的标准是使用两个空格来缩进,但这里还是推荐使用 Xcode 默认的设置。)
每个方法或者功能块之间为了结构清晰,应当只空一行。
该空格的地方要加空格,比如每个方法的开头,在 - 和 (return_type) 之间应该有且只有一个空格;写 property 时,严格按照下面的格式。

  1. @interface SomeClass : NSObject
  2. @property (noatomic, weak) UIView *aView
  3. - (void)someMethod;
  4. @end
  5. @implementation SomeClass
  6. - (void)setAView:(NSInteger )aview {
  7. }
  8. - (void)someMethod {
  9. }
  10. @end

方法书写

先不讨论一个方法带很多参数好不好,假设真的有很多参数导致方法名很长,应该用 : 对齐,每个参数一行,以提高可阅读性。

  1. - (id)initWithModel:(IPCModle)model
  2. connectType:(IPCConnectType)connectType
  3. resolution:(IPCResolution)resolution
  4. authName:(NSString *)authName
  5. password:(NSString *)password
  6. mac:(NSString *)mac
  7. azIp:(NSString *)az_ip
  8. azDns:(NSString *)az_dns
  9. token:(NSString *)token
  10. email:(NSString *)email
  11. delegate:(id)delegate;

反之如果只有两三个参数,就不要这样分行写了,一行解决即可。

  1. - (id)initWithAuthName:(NSString *)authName password:(NSString *)password;

方法调用

函数调用不要分行,统一单行写完,让编译器自动换行即可。特别是有 block 嵌套的时候,分行会非常难看。一般写完代码的时候可以用一个小技巧来格式化代码:选中代码,然后先按 Command + Alt + [,再按 Command + Alt + ]。就是把这一段代码往上移一行,再往下移一行,回到原来的样子,但是会经过 xCode 的排版,也就达到格式化代码的效果。
例如用:

  1. // blocks are easily readable
  2. [UIView animateWithDuration:1.0 animations:^{
  3. // something
  4. } completion:^(BOOL finished) {
  5. // something
  6. }];

而不是

  1. // colon-aligning makes the block indentation hard to read
  2. [UIView animateWithDuration:1.0
  3. animations:^{
  4. // something
  5. }
  6. completion:^(BOOL finished) {
  7. // something
  8. }];

if 语句

表达式大括号和其他大括号(if/else/switch/while 等)总是在同一行语句打开但在新行中关闭。如果没有 else 并且括号内只有一行语句,可以和 if 语句同行,并且不需要括号。

  1. if (user.isHappy) {
  2. //Do something
  3. } else {
  4. //Do something else
  5. }
  6. if (somethingIsBad) return something;

switch 语句

大括号在 case 语句中并不是必须的,除非编译器强制要求。当一个 case 语句包含多行代码时,大括号应该加上。

  1. switch (condition) {
  2. case 1:
  3. // ...
  4. break;
  5. case 2: {
  6. // ...
  7. // Multi-line example using braces
  8. break;
  9. }
  10. case 3:
  11. // ...
  12. break;
  13. default:
  14. // ...
  15. break;
  16. }

当在 switch 使用枚举类型时,default 是不需要的。例如:

  1. RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
  2. switch (menuType) {
  3. case RWTLeftMenuTopItemMain:
  4. // ...
  5. break;
  6. case RWTLeftMenuTopItemShows:
  7. // ...
  8. break;
  9. case RWTLeftMenuTopItemSchedule:
  10. // ...
  11. break;
  12. }

注释

代码中尽量少注释,让代码能自我描述。不过当需要注释的时候,能需要清楚地解释某个代码块的含义和作用。注释应当保持最新,如果不必要请删除。

点语法

  • 点语法是一种很方便封装访问方法调用的方式。当你使用点语法时,通过使用 getter 或 setter 方法,属性仍然被访问或修改。
  • 点语法应该总是被用来访问和修改属性,因为它使代码更加简洁。[ ] 符号更偏向于用在其它例子。

例如用

  1. view.backgroundColor = [UIColor orangeColor];

而不是

  1. [view setBackgroundColor:[UIColor orangeColor]];

Init 和 类构造方法

  1. - (instancetype)init
  2. {
  3. if (self = [super init]) {
  4. // ...
  5. }
  6. return self;
  7. }

当类构造方法被使用时,它应该返回类型是 instancetype 而不是 id,这样确保编译器正确地推断结果类型。

  1. @interface Airplane
  2. + (instancetype)airplaneWithTestType:(DKTestType)type;
  3. @end