文章目录
一、规范格式
1.1 规范的head file格式
@interface的body内的结构为:
properties;
class methods;
initializers;
instance methods.
#import <Foundation/Foundation.h>
@class Bar;
/**
* A sample class demonstrating good Objective-C style. All interfaces,
* categories, and protocols (read: all non-trivial top-level declarations
* in a header) MUST be commented. Comments must also be adjacent to the
* object they're documenting.
*/
@interface Foo : NSObject
/** The retained Bar. */
@property(nonatomic) Bar *bar;
/** The current drawing attributes. */
@property(nonatomic, copy) NSDictionary<NSString *, NSNumber *> *attributes;
/**
* Convenience creation method.
* See -initWithBar: for details about @c bar.
*
* @param bar The string for fooing.
* @return An instance of Foo.
*/
+ (instancetype)fooWithBar:(Bar *)bar;
/**
* Initializes and returns a Foo object using the provided Bar instance.
*
* @param bar A string that represents a thing that does a thing.
*/
- (instancetype)initWithBar:(Bar *)bar NS_DESIGNATED_INITIALIZER;
/**
* Does some work with @c blah.
*
* @param blah
* @return YES if the work was completed; NO otherwise.
*/
- (BOOL)doWorkWithBlah:(NSString *)blah;
@end
1.2 规范的source file格式
#import "Shared/Util/Foo.h"
@implementation Foo {
/** The string used for displaying "hi". */
NSString *_string;
}
+ (instancetype)fooWithBar:(Bar *)bar {
return [[self alloc] initWithBar:bar];
}
- (instancetype)init {
// Classes with a custom designated initializer should always override
// the superclass's designated initializer.
return [self initWithBar:nil];
}
- (instancetype)initWithBar:(Bar *)bar {
self = [super init];
if (self) {
_bar = [bar copy];
_string = [[NSString alloc] initWithFormat:@"hi %d", 3];
_attributes = @{
@"color" : [UIColor blueColor],
@"hidden" : @NO
};
}
return self;
}
- (BOOL)doWorkWithBlah:(NSString *)blah {
// Work should be done here.
return NO;
}
@end
二、命名要求
2.1 功能明确
例如:insertObject,removeObjectAtIndex,setBackgroundColor,完整地体现事件过程,避免出现命名模糊的现象;
不规范命名:insert,setBkgdColor;
2.2 保持一致性
若有一个方法或属性出现在不同的类中,那么它们使用相同的标识符是有必要的,这种做法能体现出它们之间的关联,也有利于多态(polymorphism)的实现;
例如:
-(NSInteger)tag;
-(void)setStringValue:(NSString*);
2.3 使用前缀
来自同一个package或framework,使用同一个前缀,由于2个字符的前缀被apple保留,一般使用最少三个字符的前缀;
由于OC没有namespace,因此采用在类名和方法名前加上前缀的方法,能有效避免命名冲突;
例如:
NS:Foundation;
NS:Application Kit;
AB:Address Book;
2.4 排版惯例
将多个单词的首字母大写,其余字母小写,然后放在一起,这种方式被称为驼峰式;
小驼峰式:对于方法名和变量名,首字母小写,其余规则不变,例如:fileExistAtPath;
大驼峰式:对于类名,除前缀外,首字母大写,其余规则不变,例如:NSRunAlertPanel;
2.5 Class和Protocal
Class要求名词性命名,例如NSScanner,UIApplication;
为了和Class做区分,Protocal通常以X-ing的形式命名,例如NSLocking;
2.6 文件名后缀
Extension | type |
---|---|
.h | C/C++/Objective-C 头文件 |
.m | Objective-C 源代码文件 |
.mm | C/C++/Objective-C 源代码文件,可以使用C++特性 |
.cc | C++源代码文件 |
.c | C源代码文件 |
三、命名规则
3.1 方法和成员命名
返回值为object,使用与该object类型相关的名词作为前缀,例如:
GOOD:-(Sandwich *)sandwich;
AVOID:-(Sandwich *)makeSandwich);
返回值为BOOL类型,方法命名要求把is作为前缀,例如:
-(BOOL)isGlorious;
约定:成员的getter方法名为它本身,而不需要额外的get作为前缀,例如:
GOOD:-(id)delegate;
AVOID:-(id)getDelegate;
尽量避免直接使用成员变量,而是使用getter方法:
GOOD:NSEnumerator *enumerator = [frogs reverseObjectEnumerator];
AVOID:NSEnumerator *enumerator = frogs.reverseObjectEnumerator;
3.2 global变量
对于声明在方法和类之外的global变量,使用g作为前缀标识,并尽量少地使用;
Example: gGlobalCounter;
3.3 枚举型变量
声明的每个枚举成员都应该具有相同的前缀:与枚举标识符相同,即使不使用namespace,这种做法也可以有效避免冲突;
typedef NS_ENUM(NSInteger, DisplayTinge) {
DisplayTingeGreen = 1,
DisplayTingeBlue = 2,
};
3.4 局部变量
// GOOD:
CLLocation *location = [self lastKnownLocation];
for (int meters = 1; meters < 10; meters++) {
reportFrogsWithinRadius(location, meters);
}
// AVOID:
int meters; // AVOID.
for (meters = 1; meters < 10; meters++) {
CLLocation *location = [self lastKnownLocation]; // AVOID.
reportFrogsWithinRadius(location, meters);
}
在ARC下,强指针和弱指针都自动声明为nil,然而,大多数的指针不具有ARC的特性,不会被初始化,因此最好在声明时就进行初始化操作,而不是先声明,再初始化;
3.5 整型无符号数
为了防止数学运算中出现细微的误差,在计算前需要把无符号整型数进行转化,把它们变为signed integer来使用;
// GOOD:
NSUInteger numberOfObjects = array.count;
for (NSInteger counter = numberOfObjects - 1; counter > 0; --counter)
// AVOID:
for (NSUInteger counter = numberOfObjects - 1; counter > 0; --counter) // AVOID.
3.6 不同位数下的变量类型
long, NSInteger, NSUInteger, 和CGFloat在32位和64位系统下的size不同,在赋值时需要考虑位数的影响;
// GOOD:
int32_t scalar1 = proto.intValue;
int64_t scalar2 = proto.longValue;
NSUInteger numberOfObjects = array.count;
CGFloat offset = view.bounds.origin.x;
四、总结
资料地址:
https://github.com/google/styleguide/blob/gh-pages/objcguide.md;