参考资料:
• Apple: Coding Guidelines for Cocoa
• Google: Objective-C Style Guide
• Three20: Source code style guildelines
正文:
• 格式化代码
◦ 指针“*”号的位置
▪ 如:NSString *varName;
◦ 空格 VS tabs
▪ 只允许使用空格,将编辑器设置为1个TAB = 2个字符缩进
◦ 每行的长度
▪ 每行最多不得超过100个字符
▪ 以15寸Macbook Pro的大小,每行100个字符时能最大化地同时容下编辑器和iPhone模拟器
▪ Google的80字符的标准有点少,这导致过于频繁的换行(Objectve-C的代码一般都很长)
▪ 通过 “Xcode => Preferences => TextEditing => 勾选Show Page Guide / 输入
100 => OK” 来设置提醒
◦ 方法的声明和定义
▪ 在 – 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 {
…
}
◦ 方法的调用
▪ 调用方法沿用声明方法的习惯。例外:如果给定源文件已经遵从某种习惯,继续遵从那种习惯。
▪ 所有参数应在同一行中,或者每个参数占用一行且使用冒号对齐。如:
[myObject doFooWith:arg1 name:arg2 error:arg3];
或
[myObject doFooWith:arg1
name:arg2
error:arg3];
▪ 和方法的声明一样,如果无法使用冒号对齐时,每个参数一行、缩进4个字符、垂直对其(而非
使用冒号对齐)。如:
[myObj short:arg1
longKeyword:arg2
evenLongerKeyword:arg3];
◦ @public 和 @private
▪ @public 和 @private使用单独一行,且缩进1个字符
◦ Protocals
▪ 类型标示符、代理名称、尖括号间不留空格。
▪ 该规则同样适用于:类声明、实例变量和方法声明。如:
@interface MyProtocoledClass : NSObject<NSWindowDelegate> {
@private
id<MyFancyDelegate> _delegate;
}
- (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
@end
▪ 如果类声明中包含多个protocal,每个protocal占用一行,缩进2个字符。如:
@interface CustomViewController : ViewController<
AbcDelegate,
DefDelegate
> {
…
}
• 命名
◦ 类名
▪ 类名(及其category name 和 protocal name)的首字母大写,写使用首字母大写的形式
分割单词
▪ 在面向特定应用的代码中,类名应尽量避免使用前缀,每个类都使用相同的前缀影响可读性。
▪ 在面向多应用的代码中,推荐使用前缀。如:GTMSendMessage
◦ Category Name
▪ 待完善
◦ 方法名
▪ 方法名的首字母小写,且使用首字母大写的形式分割单词。方法的参数使用相同的规则。
▪ 方法名+参数应尽量读起来像一句话(如:)。在这里查看苹果对方法命名的规范。
▪ getter的方法名和变量名应相同。不允许使用“get”前缀。如:
- (id) getDelegate; // 禁止
- (id)delegate; // 对头
▪ 本规则仅针对Objective-C代码,C++代码使用C++的习惯
◦ 变量名
▪ 变量名应使用容易意会的应用全称,且首字母小写,且使用首字母大写的形式分割单词
▪ 成员变量使用“_”作为前缀(如:“NSString *_varName;”。虽然这与苹果的标准(使
用“_”作为后缀)相冲突,但基于以下原因,仍使用“_”作为前缀。
▪ 使用“_”作为前缀,更容易在有代码自动补全功能的IDE中区分“属性
(self.userInfo)”和“成员变量(_userInfo)”
▪ 常量(#define, enums, const等)使用小写“k”作为前缀,首字母大写来分割单词。如:
kInvalidHandle
• 注释
◦ 待完善
• Cocoa 和 Objective-C特有的规则
◦ 成员变量使用 @private。如:
@interface MyClass : NSObject {
@private
id _myInstanceVariable;
}
// public accessors, setter takes ownership
- (id)myInstanceVariable;
- (void)setMyInstanceVariable:(id)theVar;
@end
◦ Indentify Designated Initializer
▪ 待完善
◦ Override Desingated Initializer
▪ 待完善
◦ 初始化
▪ 在初始化方法中,不要将变量初始化为“0”或“nil”,那是多余的
▪ 内存中所有的新创建的对象(isa除外)都是0,所以不需要重复初始化为“0”或“nil”
◦ 避免显式的调用 +new 方法
▪ 禁止直接调用 NSObject 的类方法 +new,也不要在子类中重载它。使用alloc和init方法
◦ 保持公共API的简洁性
▪ 待完善
◦ #import VS #include
▪ 使用 #import 引入Ojbective-C和Ojbective-C++头文件,使用 #include 引入C和C++头
文件
◦ import根框架(root frameworks),而非各单个文件
▪ 虽然有时我们仅需要框架(如Cocoa 或 Foundation)的某几个头文件,但引入根文件编译
器会运行的更快。因为根框架(root frameworks)一般会预编译,所以加载会更快。再次强
调:使用 #import 而非 #include 来引入Objective-C框架。如:
#import <Foundation/NSArray.h> // 禁止
#import <Foundation/NSString.h>
…
#import <Foundation/Foundation.h> // 对头
◦ 创建对象时尽量使用autorelease
▪ 创建临时对象时,尽量同时在同一行中 autorelease 掉,而非使用单独的 release 语句
▪ 虽然这样会稍微有点慢,但这样可以阻止因为提前 return 或其他意外情况导致的内存泄露。
通盘来看这是值得的。如:
// 避免这样使用(除非有性能的考虑)
MyController* controller = [[MyController alloc] init];
// … 这里的代码可能会提前return …
[controller release];
// 这样更好
MyController* controller = [[[MyController alloc] init] autorelease];
◦ 先autorelease,再retain
▪ 在为对象赋值时,遵从“先autorelease,再retain”
▪ 在将一个新创建的对象赋给变量时,要先将旧对象release掉,否则会内存泄露。市面上有很
多方法来handle这种情况,这里选择“先autorelease,再retain”的方法,这种方法不易引
入error。注意:在循环中这种方法会“填满”autorelease pool,稍稍影响效率,但是
Google和我(
)认为这个代价是可以接受的。如:
- (void)setFoo:(GMFoo *)aFoo {
[foo_ autorelease]; // 如果foo_和aFoo是同一个对象(foo_ == aFoo),
dealloc不会被调用
foo_ = [aFoo retain];
}
◦ dealloc的顺序要与变量声明的顺序相同
▪ 这有利于review代码
▪ 如果dealloc中调用其他方法来release变量,将被release的变量以注释的形式标注清楚
◦ NSString的属性的setter使用“copy”
▪ 禁止使用retain,以防止意外的修改了NSString变量的值。如:
- (void)setFoo:(NSString *)aFoo {
[foo_ autorelease];
foo_ = [aFoo copy];
}
或
@property (nonatomic, copy) NSString *aString;
◦ 避免抛出异常(Throwing Exceptions)
▪ 待完善
◦ 对 nil 的检查
▪ 仅在有业务逻辑需求时检查 nil,而非为了防止崩溃
▪ 向 nil 发送消息不会导致系统崩溃,Objective-C运行时负责处理。
◦ 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、_Bool和bool之间的转换是安全的,但是BOOL和Boolean间的转换不是安全的,所以
将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];
}
▪ 禁止直接将BOOL和YES/NO比较,如:
// 禁止
BOOL great = [foo isGreat];
if (great == YES)
…
// 对头
BOOL great = [foo isGreat];
if (great)
…
◦ 属性
▪ 命名:与去掉“_”前缀的成员变量相同,使用@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
◦ Delegate Pattern(委托)
▪ delegate对象使用assign,禁止使用retain。因为retain会导致循环索引导致内存泄露,
并且此类型的内存泄露无法被Instrument发现,极难调试
▪ 成员变量命名为_delegate,属性名为delegate
◦ Model/View/Controller
▪ Model和View分离
▪ 不多解释
▪ Controller独立于View和Controller
▪ 不要在与view相关的类中添加过多的业务逻辑代码,这让代码的可重用性很差
▪ Controller负责业务逻辑代码,且Controller的代码与view尽量无关
▪ 使用 @protocal 定义回调APIs,如果并非所有方法都是必须的,使用 @optional 标示
• 其他
◦ init方法和dealloc方法是是最常用的方法,所以将他们放在类实现的开始位置
◦ 使用空格将相同的变量、属性对齐,使用换行分组
相关推荐
一份用于ios中object-C的编程规范指南,新手可以看看,养成自己的代码习惯
学习Object C很好的资料,基本概念,编码规范,是学习iPhone开发很好的参考资料
JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。[编辑本段]JSON与XML的比较 ◆可读性 ...
OSSC完全采用C语言开发,并实现了类似面向对象的调用方式,遵循了良好的编码规范,目前OSSC除了提供了OSS开放接口文档中所描述的四大类功能外(Bucket 操作、Object 操作、Multipart Upload操作、Object Group 操作...
基本功能该实现严格符合 RFC 4627 中定义的规范、“JavaScript Object Notation (JSON)”以及 Unicode 标准版本 6.0 中发布的规范和指南。 “JSON 解析器”可以读取任何 Unicode 编码方案的 JSON 文本,即 UTF-8、...
中农大线上作业Java语言与面向对象程序设计A-F(1...描述和表示 参考答案:C 您的答案:B 20、所谓面向对象程序设计语言(Object-Oriented Programming Language)简称"( )"。 A.POOL B.OODL C.OOPL D.MUL 参考
Project-Setting-Link中的Object/Library Modules: kernel32.lib user32.lib ... xxx.lib之类的内容最后增加: osipparser2.lib 保存工程后再次编译,即可成功编译...
并提供编码规则检查,规范软件人员的编码行为。 由于PC-LINT对于一般程序员来说可能比较陌生,有好多人安装了也不知道怎样配置和使用。 下面我就根据自己的安装和配置心得对PC-Lint的安装、配置及使用进行下详细...
Ruby的JSON实现 描述 这是根据RFC 7159 的JSON规范的实现。 从版本1.0.0开始,将提供两个变体: ... 要对未经UTF-8编码的原始二进制字符串进行编码,请使用String的to_json_raw_object方法(该方法生成一个
-修正Alert消息中引号未编码导致的JS错误(feedback:sun1299shine)。 +集成extjs3.0.3。 -修正弹出对话框的宽度计算错误(会保持最小的状态)。 -增加新的皮肤Gray。 -为示例工程添加改变语言和皮肤的下拉列表。...
oracle 甲骨文 获得最高认证级别的ISO标准安全认证,性能最高, 保持开放平台下的TPC-D和TPC-C的世界记录。但价格不菲 大型企业 db2 IBM DB2在企业级的应用最为广泛, 在全球的500家最大的企业中,几乎85%以上用DB2...
W3C组织正在研究一种名为RDF(Resource Description Framework)的metadata处理方法,可以自动交换信息,W3C宣称,使用RDF配合数字签名,将使网络中存在"真实可信"的电子商务。 六.显示 单独用XMl不能显示页面,...
java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象...
12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...
12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...
O Object 对象(Java对象) : 把xml文件封装成Java对象 M Model 模型 解析过程中用到的类: Document Node(节点) Element (元素) Attribute(属性) - Attr Text(文本) ...
Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,...
java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象提供...
本规范尝试满足大型主机、微型主机、个人工作站、和TACs 的不同需求。例如,容易实现协议的设计。 Java EJB中有、无状态SessionBean的两个例子 两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取...