iOS代码规范(翻译自官方文档)

点击查看简书原文

一. 格式化代码

1. 指针“*”号的位置

▪ 如:NSString *varName; 

2. 空格 VS tabs

▪ 只允许使用空格,将编辑器设置为1个TAB = 2个字符缩进

3. 每行的长度

▪ 每行最多不得超过100个字符
▪ 以15寸Macbook Pro的大小,每行100个字符时能最大化地同时容下编辑器和iPhone模拟器
▪ Google的80字符的标准有点少,这导致过于频繁的换行(Objectve-C的代码一般都很长)
▪ 通过 “Xcode => Preferences => TextEditing => 勾选Show Page Guide / 输入
100 => OK” 来设置提醒

4. 方法的声明和定义

▪ 在 - OR + 和返回值之间留1个空格,方法名和第一个参数间不留空格。如:

- (void)doSomethingWithString:(NSString *)theString { 
... 
} 
//当参数过长时,每个参数占用一行,以冒号对齐。如: 
- (void)doSomethingWith:(GTMFoo *)theFoo 
rect:(NSRect)theRect 
interval:(float)theInterval { 
... 
} 

▪ 如果方法名比参数名短,每个参数占用一行,至少缩进4个字符,且为垂直对齐(而非使用冒号
对齐)。如:

- (void)short:(GTMFoo *)theFoo 
longKeyword:(NSRect)theRect 
evenLongerKeyword:(float)theInterval { 
... 
} 

5. 方法的调用

▪ 调用方法沿用声明方法的习惯。例外:如果给定源文件已经遵从某种习惯,继续遵从那种习惯。
▪ 所有参数应在同一行中,或者每个参数占用一行且使用冒号对齐。如:

[myObject doFooWith:arg1 name:arg2 error:arg3]; 
或 
[myObject doFooWith:arg1 
name:arg2 
error:arg3]; 

▪ 和方法的声明一样,如果无法使用冒号对齐时,每个参数一行、缩进4个字符、垂直对其(而非
使用冒号对齐)。如:

[myObj short:arg1 
longKeyword:arg2 
evenLongerKeyword:arg3]; 

6. @public 和 @private

▪ @public 和 @private使用单独一行,且缩进1个字符

7. Protocals

▪ 类型标示符、代理名称、尖括号间不留空格。
▪ 该规则同样适用于:类声明、实例变量和方法声明。如:

@interface MyProtocoledClass : NSObject<NSWindowDelegate> { 
@private 
id<MyFancyDelegate> _delegate; 
} 

- (void)setDelegate:(id<MyFancyDelegate>)aDelegate; 

@end 

▪ 如果类声明中包含多个protocal,每个protocal占用一行,缩进2个字符。如:

@interface CustomViewController : ViewController< 
AbcDelegate, 
DefDelegate 
> { 
... 
} 

二. 命名

1. 类名

▪ 类名(及其category nameprotocol name)的首字母大写,写使用首字母大写的形式

2. 分割单词

▪ 在面向特定应用的代码中,类名应尽量避免使用前缀,每个类都使用相同的前缀影响可读性。
▪ 在面向多应用的代码中,推荐使用前缀。如:GTMSendMessage

3. 方法名

▪ 方法名的首字母小写,且使用首字母大写的形式分割单词。方法的参数使用相同的规则。
▪ 方法名+参数应尽量读起来像一句话(如:)。在这里查看苹果对方法命名的规范。
▪ getter的方法名和变量名应相同。不允许使用“get”前缀。如:

- (id) getDelegate; // 禁止 
- (id)delegate; // 对头 

▪ 本规则仅针对Objective-C代码,C++代码使用C++的习惯

4. 变量名

▪ 变量名应使用容易意会的应用全称,且首字母小写,且使用首字母大写的形式分割单词
▪ 成员变量使用“”作为前缀(如:“NSString *_varName;”。虽然这与苹果的标准相冲突,但基于以下原因,仍使用“”作为前缀。 )
▪ 使用“_”作为前缀,更容易在有代码自动补全功能的IDE中区分“属性
(self.userInfo)”和“成员变量(_userInfo)”
▪ 常量(#define, enums, const等)使用小写“k”作为前缀,首字母大写来分割单词。如:

kInvalidHandle

三. Cocoa 和 Objective-C特有的规则

1. 成员变量使用 @private。如:

@interface MyClass : NSObject { 
@private 
id _myInstanceVariable; 
} 
// public accessors, setter takes ownership 
- (id)myInstanceVariable; 
- (void)setMyInstanceVariable:(id)theVar; 
@end 

2. 初始化

▪ 在初始化方法中,不要将变量初始化为“0”或“nil”,那是多余的
▪ 内存中所有的新创建的对象(isa除外)都是0,所以不需要重复初始化为“0”或“nil”

3. 避免显式的调用 +new 方法

▪ 禁止直接调用 NSObject 的类方法 +new,也不要在子类中重载它。使用alloc和init方法

4. 保持公共API的简洁性

5. #import VS #include

▪ 使用 #import 引入Ojbective-COjbective-C++头文件,使用 #include 引入CC++
文件

6. import 根框架(root frameworks),而非各单个文件

▪ 虽然有时我们仅需要框架(如Cocoa 或 Foundation)的某几个头文件,但引入根文件,编译器会运行的更快。因为根框架(root frameworks)一般会预编译,所以加载会更快。再次强
调:使用 #import 而非 #include 来引入Objective-C框架。如:

#import <Foundation/NSArray.h> // 禁止 
#import <Foundation/NSString.h> 
... 
#import <Foundation/Foundation.h> // 对头

7. 创建对象时尽量使用autorelease

▪ 创建临时对象时,尽量同时在同一行中 autorelease 掉,而非使用单独的 release 语句
▪ 虽然这样会稍微有点慢,但这样可以阻止因为提前 return 或其他意外情况导致的内存泄露。
通盘来看这是值得的。如:

// 避免这样使用(除非有性能的考虑) 
MyController* controller = [[MyController alloc] init]; 
// ... 这里的代码可能会提前return ... 
[controller release]; 
// 这样更好 
MyController* controller = [[[MyController alloc] init] autorelease]; 

8. 先autorelease,再retain

▪ 在为对象赋值时,遵从“先autorelease,再retain
▪ 在将一个新创建的对象赋给变量时,要先将旧对象release掉,否则会内存泄露。市面上有很多方法来handle这种情况,这里选择“先autorelease,再retain”的方法,这种方法不易引入error。注意:在循环中这种方法会“填满”autorelease pool,稍稍影响效率,但是
Google和我( :P )认为这个代价是可以接受的。如:

- (void)setFoo:(GMFoo *)aFoo { 
  [foo_ autorelease]; // 如果foo_和aFoo是同一个对象(foo_ == aFoo),dealloc不会被调用 
  foo_ = [aFoo retain]; 
} 

9. dealloc的顺序要与变量声明的顺序相同

▪ 这有利于review代码
▪ 如果dealloc中调用其他方法来release变量,将被release的变量以注释的形式标注清楚

10. NSString的属性的setter使用“copy

▪ 禁止使用retain,以防止意外的修改了NSString变量的值。如:

- (void)setFoo:(NSString *)aFoo { 
  [foo_ autorelease]; 
  foo_ = [aFoo copy]; 
} 

@property (nonatomic, copy) NSString *aString; 

11. 避免抛出异常(Throwing Exceptions

12. 对 nil 的检查

▪ 仅在有业务逻辑需求时检查 nil,而非为了防止崩溃
▪ 向 nil 发送消息不会导致系统崩溃,Objective-C运行时负责处理。

13. BOOL 陷阱

▪ 将int值转换为BOOL时应特别小心。避免直接和YES比较
Objective-C中,BOOL被定义为unsigned char,这意味着除了YES (1)NO (0)外它还可以是其他值。禁止将int直接转换(cast or convert)为BOOL
▪ 常见的错误包括:将数组的大小、指针值或位运算符的结果转换(cast or convert)BOOL,因为该BOOL值的结果取决于整型值的最后一位
▪ 将整型值转换为BOOL的方法:使用三元运算符返回YES / NO,或使用位运算符(&&, ||, !)
BOOL_Boolbool之间的转换是安全的,但是BOOLBoolean间的转换不是安全的,所以将Boolean看成整型值。
▪ 在 Objective-C 中,只允许使用BOOL
▪ 如:

// 禁止 
- (BOOL)isBold { 
  return [self fontTraits] & NSFontBoldTrait; 
} 
- (BOOL)isValid { 
  return [self stringValue]; 
} 
// 对头 
- (BOOL)isBold { 
  return ([self fontTraits] & NSFontBoldTrait) ? YES : NO; 
} 
- (BOOL)isValid { 
  return [self stringValue] != nil; 
} 
- (BOOL)isEnabled { 
  return [self isValid] && [self isBold]; 
} 

▪ 禁止直接将BOOLYES/NO比较,如:

// 禁止 
BOOL great = [foo isGreat]; 
if (great == YES) 
... 
// 对头 
BOOL great = [foo isGreat]; 
if (great) 
... 

14. 属性

▪ 命名:与去掉“_”前缀的成员变量相同,使用@synthesize将二者联系起来。如:

// abcd.h 
@interface MyClass : NSObject { 
@private 
NSString *_name; 
} 
@property (copy, nonatomic) NSString *name; 
@end 
// abcd.m 
@implementation MyClass 
@synthesize name = _name; 
@end 

▪ 位置:属性的声明紧随成员变量块之后,中间空一行,无缩进。如上例所示
▪ 严把权限:对不需要外部修改的属性使用readonly
NSString使用copy而非retain
CFType使用@dynamic, 禁止使用@synthesize
▪ 除非必须,使用nonatomic
Cocoa Pattern

15. Delegate Pattern(委托)

delegate对象使用assign,禁止使用retain。因为retain会导致循环索引导致内存泄露,并且此类型的内存泄露无法被Instrument发现,极难调试 .
▪ 成员变量命名为_delegate,属性名为delegate

16. Model/View/Controller

ModelView分离
Controller独立于ViewController
▪ 不要在与view相关的类中添加过多的业务逻辑代码,这让代码的可重用性很差
Controller负责业务逻辑代码,且Controller的代码与view尽量无关
▪ 使用 @protocal 定义回调APIs,如果并非所有方法都是必须的,使用@optional标示

四. 其他

1.init方法和dealloc方法是是最常用的方法,所以将他们放在类实现的开始位置

2. 使用空格将相同的变量、属性对齐,使用换行分组

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • iOS编程规范0规范 0.1前言 为􏰀高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可 测试、高效...
    iOS行者阅读 4,446评论 21 35
  • 37.cocoa内存管理规则 1)当你使用new,alloc或copy方法创建一个对象时,该对象的保留计数器值为1...
    如风家的秘密阅读 838评论 0 4
  • 推荐文章:禅与 Objective-C 编程艺 前言 为􏰀高产品代码质量,指导广大软件开发人员编写出简洁、可维护、...
    WolfTin阅读 2,755评论 0 1
  • 1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch...
    阳光的大男孩儿阅读 4,971评论 0 13
  • 1.1 什么是自动引用计数 概念:在 LLVM 编译器中设置 ARC(Automaitc Reference Co...
    __silhouette阅读 5,120评论 1 17