IOS开发-代码规范

  • 代码风格的重要性对于一个团队和项目来说不言而喻。网上有许多 Objective-C 的代码风格,但这份简洁而又最符合苹果的规范,同时有助于养成良好的代码习惯,也是我们团队一直遵循的代码风格。
  • 写法没有对错,只是一种规范。各有各的一种规范,仅供参考。

# 纽约时报 移动团队 Objective-C 规范指南

这份规范指南概括了纽约时报 iOS 团队的代码约定。

## 介绍

关于这个编程语言的所有规范,如果这里没有写到,那就在苹果的文档里:

* [Objective-C 编程语言][Introduction_1]

* [Cocoa 基本原理指南][Introduction_2]

* [Cocoa 编码指南][Introduction_3]

* [iOS 应用编程指南][Introduction_4]

[Introduction_1]:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html

[Introduction_2]:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/Introduction/Introduction.html

[Introduction_3]:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html

[Introduction_4]:http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/Introduction/Introduction.html

## 目录

* [点语法](#点语法)

* [间距](#间距)

* [条件判断](#条件判断)

* [三目运算符](#三目运算符)

* [错误处理](#错误处理)

* [方法](#方法)

* [变量](#变量)

* [命名](#命名)

* [注释](#注释)

* [Init 和 Dealloc](#init-和-dealloc)

* [字面量](#字面量)

* [CGRect 函数](#CGRect-函数)

* [常量](#常量)

* [枚举类型](#枚举类型)

* [位掩码](#位掩码)

* [私有属性](#私有属性)

* [图片命名](#图片命名)

* [布尔](#布尔)

* [单例](#单例)

* [导入](#导入)

* [Xcode 工程](#Xcode-工程)

## 点语法***************

应该 **始终** 使用点语法来访问或者修改属性,访问其他实例时首选括号。

**推荐:**

1 ```objc
2
3 view.backgroundColor = [UIColor orangeColor];
4
5 [UIApplication sharedApplication].delegate;
6
7 ```

**反对:**

1 ```objc
2
3 [view setBackgroundColor:[UIColor orangeColor]];
4
5 UIApplication.sharedApplication.delegate;
6
7 ```

## 间距***************

* 一个缩进使用 4 个空格,永远不要使用制表符(tab)缩进。请确保在 Xcode 中设置了此偏好。

* 方法的大括号和其他的大括号(`if`/`else`/`switch`/`while` 等等)始终和声明在同一行开始,在新的一行结束。

**推荐:**

 1 ```objc
 2
 3 if (user.isHappy) {
 4
 5 // Do something
 6
 7 }
 8
 9 else {
10
11 // Do something else
12
13 }
14
15 ```

* 方法之间应该正好空一行,这有助于视觉清晰度和代码组织性。在方法中的功能块之间应该使用空白分开,但往往可能应该创建一个新的方法。

* `@synthesize` 和 `@dynamic` 在实现中每个都应该占一个新行。

## 条件判断***************

条件判断主体部分应该始终使用大括号括住来防止[出错][Condiationals_1],即使它可以不用大括号(例如它只需要一行)。这些错误包括添加第二行(代码)并希望它是 if 语句的一部分时。还有另外一种[更危险的][Condiationals_2],当 if 语句里面的一行被注释掉,下一行就会在不经意间成为了这个 if 语句的一部分。此外,这种风格也更符合所有其他的条件判断,因此也更容易检查。

**推荐:**

1 ```objc
2
3 if (!error) {
4
5     return success;
6
7 }
8
9 ```

**反对:**

1 ```objc
2
3 if (!error)
4
5     return success;
6
7 ``

1 ```objc
2
3 if (!error) return success;
4
5 ```

[Condiationals_1]:(https://github.com/NYTimes/objective-c-style-guide/issues/26#issuecomment-22074256)

[Condiationals_2]:http://programmers.stackexchange.com/a/16530

### 三目运算符***************

三目运算符,? ,只有当它可以增加代码清晰度或整洁时才使用。单一的条件都应该优先考虑使用。多条件时通常使用 if 语句会更易懂,或者重构为实例变量。

**推荐:**

1 ```objc
2
3 result = a > b ? x : y;
4
5 ```

**反对:**

1 ```objc
2
3 result = a > b ? x = c > d ? c : d : y;
4
5 ```

## 错误处理***************

当引用一个返回错误参数(error parameter)的方法时,应该针对返回值,而非错误变量。

**推荐:**

 1 ```objc
 2
 3 NSError *error;
 4
 5 if (![self trySomethingWithError:&error]) {
 6
 7     // 处理错误
 8
 9 }
10
11 ```

**反对:**

 1 ```objc
 2
 3 NSError *error;
 4
 5 [self trySomethingWithError:&error];
 6
 7 if (error) {
 8
 9     // 处理错误
10
11 }
12
13 ```

一些苹果的 API 在成功的情况下会写一些垃圾值给错误参数(如果非空),所以针对错误变量可能会造成虚假结果(以及接下来的崩溃)。

## 方法***************

在方法签名中,在 -/+ 符号后应该有一个空格。方法片段之间也应该有一个空格。

**推荐:**

1 ```objc
2
3 - (void)setExampleText:(NSString *)text image:(UIImage *)image;
4
5 ```

## 变量

变量名应该尽可能命名为描述性的。除了 `for()` 循环外,其他情况都应该避免使用单字母的变量名。

星号表示指针属于变量,例如:`NSString *text` 不要写成 `NSString* text` 或者 `NSString * text` ,常量除外。

尽量定义属性来代替直接使用实例变量。除了初始化方法(`init`, `initWithCoder:`,等), `dealloc` 方法和自定义的 setters 和 getters 内部,应避免直接访问实例变量。更多有关在初始化方法和 dealloc 方法中使用访问器方法的信息,参见[这里][Variables_1]。

**推荐:**

1 ```objc
2
3 @interface NYTSection: NSObject
4
5  @property (nonatomic) NSString *headline;
6
7 @end
8
9 ```

**反对:**

1 ```objc
2
3 @interface NYTSection : NSObject {
4
5     NSString *headline;
6
7 }
8
9 ```

[Variables_1]:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW6

## 变量限定符***************

当涉及到[在 ARC 中被引入][Variable_Qualifiers_1]变量限定符时,

限定符 (`__strong`, `__weak`, `__unsafe_unretained`, `__autoreleasing`) 应该位于星号和变量名之间,如:`NSString * __weak text`。

[Variable_Qualifiers_1]:(https://developer.apple.com/library/ios/releasenotes/objectivec/rn-transitioningtoarc/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4)

## 命名

尽可能遵守苹果的命名约定,尤其那些涉及到[内存管理规则][Naming_1],([NARC][Naming_2])的。

长的和描述性的方法名和变量名都不错。

**推荐:**

1 ```objc
2
3 UIButton *settingsButton;
4
5 ``

**反对:**

1 ```objc
2
3 UIButton *setBut;
4
5 ```

类名和常量应该始终使用三个字母的前缀(例如 `NYT`),但 Core Data 实体名称可以省略。为了代码清晰,常量应该使用相关类的名字作为前缀并使用驼峰命名法。

**推荐:**

1 ```objc
2
3 static const NSTimeInterval NYTArticleViewControllerNavigationFadeAnimationDuration = 0.3;
4
5 ```

**反对:**

1 ```objc
2
3 static const NSTimeInterval fadetime = 1.7;
4
5 ```

属性和局部变量应该使用驼峰命名法并且首字母小写。

为了保持一致,实例变量应该使用驼峰命名法命名,并且首字母小写,以下划线为前缀。这与 LLVM 自动合成的实例变量相一致。

**如果 LLVM 可以自动合成变量,那就让它自动合成。**

**推荐:**

1 ```objc
2
3 @synthesize descriptiveVariableName = _descriptiveVariableName;
4
5 ```

**反对:**

1
2
3 ```objc
4
5 id varnm;
6
7 ```

[Naming_1]:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

[Naming_2]:http://stackoverflow.com/a/2865194/340508

## 注释***************

当需要的时候,注释应该被用来解释 **为什么** 特定代码做了某些事情。所使用的任何注释必须保持最新否则就删除掉。

通常应该避免一大块注释,代码就应该尽量作为自身的文档,只需要隔几行写几句说明。这并不适用于那些用来生成文档的注释。

## init 和 dealloc

`dealloc` 方法应该放在实现文件的最上面,并且刚好在 `@synthesize` 和 `@dynamic` 语句的后面。在任何类中,`init` 都应该直接放在 `dealloc` 方法的下面。

`init` 方法的结构应该像这样:

 1 ```objc
 2
 3 - (instancetype)init {
 4
 5     self = [super init]; // 或者调用指定的初始化方法
 6
 7     if (self) {
 8
 9         // Custom initialization
10
11     }
12
13
14
15     return self;
16
17 }
18
19 ```

## 字面量***************

每当创建 `NSString`, `NSDictionary`, `NSArray`,和 `NSNumber` 类的不可变实例时,都应该使用字面量。要注意 `nil` 值不能传给 `NSArray` 和 `NSDictionary` 字面量,这样做会导致崩溃。

**推荐:**

 1 ```objc
 2
 3 NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
 4
 5 NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};
 6
 7 NSNumber *shouldUseLiterals = @YES;
 8
 9 NSNumber *buildingZIPCode = @10018;
10
11 ```

**反对:**

 1 ```objc
 2
 3 NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
 4
 5 NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
 6
 7 NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
 8
 9 NSNumber *buildingZIPCode = [NSNumber numberWithInteger:10018];
10
11 ```

## CGRect 函数***************

当访问一个 `CGRect` 的 `x`, `y`, `width`, `height` 时,应该使用[`CGGeometry` 函数][CGRect-Functions_1]代替直接访问结构体成员。苹果的 `CGGeometry` 参考中说到:

> All functions described in this reference that take CGRect data structures as inputs implicitly standardize those rectangles before calculating their results. For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

**推荐:**

 1 ```objc
 2
 3 CGRect frame = self.view.frame;
 4
 5
 6
 7 CGFloat x = CGRectGetMinX(frame);
 8
 9 CGFloat y = CGRectGetMinY(frame);
10
11 CGFloat width = CGRectGetWidth(frame);
12
13 CGFloat height = CGRectGetHeight(frame);
14
15 ```

**反对:**

 1 ```objc
 2
 3 CGRect frame = self.view.frame;
 4
 5
 6
 7 CGFloat x = frame.origin.x;
 8
 9 CGFloat y = frame.origin.y;
10
11 CGFloat width = frame.size.width;
12
13 CGFloat height = frame.size.height;
14
15 ```

[CGRect-Functions_1]:http://developer.apple.com/library/ios/#documentation/graphicsimaging/reference/CGGeometry/Reference/reference.html

## 常量***************

常量首选内联字符串字面量或数字,因为常量可以轻易重用并且可以快速改变而不需要查找和替换。常量应该声明为 `static` 常量而不是 `#define` ,除非非常明确地要当做宏来使用。

**推荐:**

1 ```objc
2
3 static NSString * const NYTAboutViewControllerCompanyName = @"The New York Times Company";
4
5
6
7 static const CGFloat NYTImageThumbnailHeight = 50.0;
8
9 ```

**反对:**

1 ```objc
2
3 #define CompanyName @"The New York Times Company"
4
5
6
7 #define thumbnailHeight 2
8
9 ```

## 枚举类型***************

当使用 `enum` 时,建议使用新的基础类型规范,因为它具有更强的类型检查和代码补全功能。现在 SDK 包含了一个宏来鼓励使用使用新的基础类型 - `NS_ENUM()`

**推荐:**

 1 ```objc
 2
 3 typedef NS_ENUM(NSInteger, NYTAdRequestState) {
 4
 5     NYTAdRequestStateInactive,
 6
 7     NYTAdRequestStateLoading
 8
 9 };
10
11 ```

## 位掩码***************

当用到位掩码时,使用 `NS_OPTIONS` 宏。

**举例:**

 1 ```objc
 2
 3 typedef NS_OPTIONS(NSUInteger, NYTAdCategory) {
 4
 5 NYTAdCategoryAutos      = 1 << 0,
 6
 7 NYTAdCategoryJobs       = 1 << 1,
 8
 9 NYTAdCategoryRealState  = 1 << 2,
10
11 NYTAdCategoryTechnology = 1 << 3
12
13 };
14
15 ```

## 私有属性***************

私有属性应该声明在类实现文件的延展(匿名的类目)中。有名字的类目(例如 `NYTPrivate` 或 `private`)永远都不应该使用,除非要扩展其他类。

**推荐:**

 1 ```objc
 2
 3 @interface NYTAdvertisement ()
 4
 5
 6
 7 @property (nonatomic, strong) GADBannerView *googleAdView;
 8
 9 @property (nonatomic, strong) ADBannerView *iAdView;
10
11 @property (nonatomic, strong) UIWebView *adXWebView;
12
13
14
15 @end
16
17 ```

## 图片命名***************

图片名称应该被统一命名以保持组织的完整。它们应该被命名为一个说明它们用途的驼峰式字符串,其次是自定义类或属性的无前缀名字(如果有的话),然后进一步说明颜色 和/或 展示位置,最后是它们的状态。

**推荐:**

* `RefreshBarButtonItem` / `[email protected]` 和 `RefreshBarButtonItemSelected` / `[email protected]`

* `ArticleNavigationBarWhite` / `[email protected]` 和 `ArticleNavigationBarBlackSelected` / `[email protected]`.

图片目录中被用于类似目的的图片应归入各自的组中。

## 布尔***************

因为 `nil` 解析为 `NO`,所以没有必要在条件中与它进行比较。永远不要直接和 `YES` 进行比较,因为 `YES` 被定义为 1,而 `BOOL` 可以多达 8 位。

这使得整个文件有更多的一致性和更大的视觉清晰度。

**推荐:**

1 ```objc
2
3 if (!someObject) {
4
5 }
6
7 ```

**反对:**

1 ```objc
2
3 if (someObject == nil) {
4
5 }
6
7 ```

**对于 `BOOL` 来说, 这有两种用法:**

1 ```objc
2
3 if (isAwesome)
4
5 if (![someObject boolValue])
6
7 ```

**反对:**

1 ```objc
2
3 if ([someObject boolValue] == NO)
4
5 if (isAwesome == YES) // 永远别这么做
6
7 ```

如果一个 `BOOL` 属性名称是一个形容词,属性可以省略 “is” 前缀,但为 get 访问器指定一个惯用的名字,例如:

1 ```objc
2
3 @property (assign, getter=isEditable) BOOL editable;
4
5 ```

内容和例子来自 [Cocoa 命名指南][Booleans_1] 。

[Booleans_1]:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-BAJGIIJE

## 单例***************

单例对象应该使用线程安全的模式创建共享的实例。

 1 ```objc
 2
 3 + (instancetype)sharedInstance {
 4
 5    static id sharedInstance = nil;
 6
 7
 8
 9    static dispatch_once_t onceToken;
10
11    dispatch_once(&onceToken, ^{
12
13       sharedInstance = [[self alloc] init];
14
15    });
16
17
18
19    return sharedInstance;
20
21 }
22
23 ```

这将会预防[有时可能产生的许多崩溃][Singletons_1]。

[Singletons_1]:http://cocoasamurai.blogspot.com/2011/04/singletons-your-doing-them-wrong.html

## 导入***************

如果有一个以上的 import 语句,就对这些语句进行[分组][Import_1]。每个分组的注释是可选的。

注:对于模块使用 [@import][Import_2] 语法。

```objc

// Frameworks

@import QuartzCore;

// Models

#import "NYTUser.h"

// Views

#import "NYTButton.h"

#import "NYTUserView.h"

```

[Import_1]: http://ashfurrow.com/blog/structuring-modern-objective-c

[Import_2]: http://clang.llvm.org/docs/Modules.html#using-modules

## Xcode 工程***************

为了避免文件杂乱,物理文件应该保持和 Xcode 项目文件同步。Xcode 创建的任何组(group)都必须在文件系统有相应的映射。为了更清晰,代码不仅应该按照类型进行分组,也可以根据功能进行分组。

如果可以的话,尽可能一直打开 target Build Settings 中 "Treat Warnings as Errors" 以及一些[额外的警告][Xcode-project_1]。如果你需要忽略指定的警告,使用 [Clang 的编译特性][Xcode-project_2] 。

[Xcode-project_1]:http://boredzo.org/blog/archives/2009-11-07/warnings

[Xcode-project_2]:http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas

# 其他 Objective-C 风格指南***************

如果感觉我们的不太符合你的口味,可以看看下面的风格指南:

* [Google](http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml)

* [GitHub](https://github.com/github/objective-c-conventions)

* [Adium](https://trac.adium.im/wiki/CodingStyle)

* [Sam Soffes](https://gist.github.com/soffes/812796)

* [CocoaDevCentral](http://cocoadevcentral.com/articles/000082.php)

* [Luke Redpath](http://lukeredpath.co.uk/blog/my-objective-c-style-guide.html)

* [Marcus Zarra](http://www.cimgf.com/zds-code-style-guide/)

时间: 2024-10-05 07:06:17

IOS开发-代码规范的相关文章

iOS 开发代码规范有哪些

对于刚刚入门ios的同学来说,iOS 开发代码规范是很重要的知识的,这里就给大家简单总结了一下. 一.工程规范 1.功能分类 根据所做功能的不同,分为不同的功能模块,比如登录模块,首页模块,个人模块等,根据不同的功能,代码必须要放在不同功能的文件夹下. 2.代码文件分类 不管是MVC模式,MVVM模式,或是其他设计模式,在不同的功能模块下,视图控制器(Controllers),视图(Views),模型类(Models),也必须要分别存放. 3.第三方库分类 工程中会经常使用第三方库,在引入第三方

ios开发代码规范

代码规范很重要,一个良好的代码习惯要从一开始就养成 公共类和文件的设计 (网络请求类.数据库类.Model类.View类,Controller<根据流程图>.Handle类<数据处理>.公共头文件<宏.接口的.h{URL}.常量const{通知中心的名字.一些状态码.枚举.结构体}.全局配置(适配{屏幕适配.iOS系统适配}的宏.系统版本判断.颜色值{参考图片})>) 一.文件 1.项目文件必须使用一个有意义的名字. 例如:TestDownImages 2.任何文件的命

iOS开发代码规范(通用)

例子: MFHomeViewController View: 使用View做后缀 例子: MFAlertView UITableCell:使用Cell做后缀 例子: MFNewsCell Protocol: 使用Delegate或者DataSource作为后缀 例子: UITableViewDelegate UI控件依次类推 3> 私有变量 小驼峰式命名:第一个单词以小写字母开始,后面的单词的首字母全部大写 例子:firstName.lastName 以 _ 开头,第一个单词首字母小写 例子:N

iOS团队开发代码规范

iOS 开发代码规范 1.命名 https://github.com/Chinamobo/iOS-Team-Norms/blob/master/CodeStyle.md#naming-basic-principle https://github.com/foxsofter/ios-code-style https://github.com/andy0323/iOS-Code-Specification 新建.h,.m文件时,文件名称应与

iOS软件代码规范

在梳理团队开发流程,收集相关流程资料时,在百度文档上发现的一篇iOS软件代码规范文档:写的非常完善,具有很强操作性.百度上下载时花了一个下载币,现和大家共享.下载地址:http://download.csdn.net/detail/smallhorse87/8660881 在此基础上,我添加了客户端上线前收尾工作的备忘事项: APP中是否装备了必备功能:统计,日志收集及发送,版本检测以及自动更新,用户反馈: 确保产品经理和设计师体验过了APP,签字画押.确保APP体现了产品和设计的构想,没有理解

Android开发代码规范(转)

Android开发代码规范 1.命名基本原则    在面向对象编程中,对于类,对象,方法,变量等方面的命名是非常有技巧的.比如,大小写的区分,使用不同字母开头等等.但究其本,追其源,在为一个资源其名称的时候,应该本着描述性以及唯一性这两大特征来命名,才能保证资源之间不冲突,并且每一个都便于记忆. 对于理解应用程序的逻辑流,命名方案是最有影响力的一种帮助.名称应该说明“什么”而不是“如何”.命名原则是:使名称足够长以便有一定的意义,并且足够短以避免冗长.唯一名称在编程上仅用于将各项区分开.以下几点

北京天宇联科技有限责任公司—T语言Ios开发命名规范

T语言(ttyu software language )是一种通过定义的方式自动生成原生态的android.ios和自适应各浏览的h5的web页面的三合一的软件开发语言.T语言是一种简单的,易于使用的开发软件.T语言运用TC简单开发. TC简单开发是国内首款免费多线程的图形界面脚本制作开发工具软件,支持中英文双语言编写脚本程序,综合脚本开发工具,可以说TC开脚本界先河,是免费脚本开发制作工具的首选.通过制作脚本,可以让TC简单开发代替您的双手,自动执行一系列鼠标键动作.能陪伴你每日每夜的脚本开发

web前端开发代码规范

1. 引言 对于一个多人团队来说,制定一个统一的规范是必要的,因为个性化的东西无法产生良好的聚合效果,规范化可以提高编码工作效率,使代码保持统一的风格,以便于代码整合和后期维护.本文档主要描述web项目开发中所使用的html.css.JavaScript等规范,请参与开发相关人员遵循,同时也请各位日后进行补充完善. 2. HTML/CSS规范 2.1 浏览器兼容 根据业务要求而定: 主流程测试:Chrome 30+.IE9+: 完整测试: Chrome 21.IE8+.360浏览器.微信webv

JAVA技术开发规范(4)——JASMP平台的开发代码规范

4.关于代码规范 代码规范对程序员的重要性: 1.在软件开发生命周期中,有80%的时间是用在维护上 2.几乎所有的软件维护者都不是创使人 3.迭代式开发,必须要有清晰.可读性强的代码,以便于快速迭代 4.敏捷开发时,对应文档的输出不是减少,而是更加实用,因此,可交付的易读的代码更为重要了 5.协同协同,必需确保在编码时遵循统一的规范 编码规范是必需的,每个参与人必需严格遵循该规范进行编码. 4.1.命名规范 基本原则: 1.采用英文全称进行命名 2.保持各层级名称基本统一 3.命名英文单词用全称