命名
Preferred :
UIColor *myColor = [UIColor whiteColor];
Not Preferred :
UIColor *myColour = [UIColor whiteColor];
代码组织
使用#pragma mark - 将生命周期、分类方法和代理方法分块标注管理
#pragma mark - Lifecycle
- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
#pragma mark - Custom Accessors
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}
#pragma mark - IBActions
- (IBAction)submitData:(id)sender {}
#pragma mark - Public
- (void)publicMethod {}
#pragma mark - Private
- (void)privateMethod {}
#pragma mark - Protocol conformance
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {}
#pragma mark - NSObject
- (NSString *)description {}
#pragma mark - lazy
空格
- 使用2个空格不要使用Tab键
- 方法和其他后的大括弧在第一行开始在新的一行结束。
Preferred:
if (user.isHappy) {
//Do something
} else {
//Do something else
}
Not Preferred:
if (user.isHappy)
{
//Do something
}
else {
//Do something else
}
- 在方法中的参数中间添加一个空格方便阅读。
- 优先使用自动生成,但是如果需要的话可以在实现文件中添加@ synthesize 和 @dynamic。
- 调用方法时尽量避免方法中冒号对齐。当方法中包含3个以上的参数,使用冒号对齐会增加方法的可读性。但是,当方法中包含block时Xcode 的自动对齐会让代码看起来不容易分辨。
Preferred:
// blocks are easily readable
[UIView animateWithDuration:1.0 animations:^{
// something
} completion:^(BOOL finished) {
// something
}];
Not Preferred:
// colon-aligning makes the block indentation hard to read
[UIView animateWithDuration:1.0
animations:^{
// something
}
completion:^(BOOL finished) {
// something
}];
注释
所有的注释必须保持最新或者删除,避免块注释。
命名
尽量保持苹果的命名方式,长的,描述性和变量名都很好。
Preferred:
UIButton *settingsButton;
Not Preferred:
UIButton *setBut;
对于类名和常量名一般使用三字母前缀,在coreData 实体名称可以省略。常量一般遵循驼峰命名方式,使用相关类名最为前缀。
Preferred:
static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3;
Not Preferred:
static NSTimeInterval const fadetime = 1.7;
属性命名应该遵循首字母小写的驼峰原则。尽量使用自动生成而非手动。
Preferred:
@property (strong, nonatomic) NSString *descriptiveVariableName;
Not Preferred:
id varnm;
下划线
在初始化的时候,实例变量使用下划线。局部变量不要使用下划线。
方法
在(+/-)符号后添加一个空格,关键词应该对参数有简单的描述。
关键字and的使用不建议使用在多参数的方法名中。
Preferred:
- (void)setExampleText:(NSString *)text image:(UIImage *)image;
- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;
- (id)viewWithTag:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
Not Preferred:
-(void)setT:(NSString *)text i:(UIImage *)image;
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
- (id)taggedView:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
- (instancetype)initWith:(int)width and:(int)height; // Never do this.
变量
应该使用可描述的变量名称。单字符变量名除了在for循环中使用其他情况不宜使用。
*号应该跟在变量前,NSString text not NSString text;
尽量使用私有属性代替实例变量。
Preferred:
@interface RWTTutorial : NSObject
@property (strong, nonatomic) NSString *tutorialName;
@end
Not Preferred:
@interface RWTTutorial : NSObject {
NSString *tutorialName;
}
属性
Preferred:
@property (weak, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) NSString *tutorialName;
Not Preferred:
@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic) NSString *tutorialName;
字符串属性推荐使用copy不建议使用strong。
Preferred:
@property (copy, nonatomic) NSString *tutorialName;
Not Preferred:
@property (strong, nonatomic) NSString *tutorialName;
点语法
Preferred:
NSInteger arrayCount = [self.array count];
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;
Not Preferred:
NSInteger arrayCount = self.array.count;
[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;
字面量
NSString, NSDictionary, NSArray, and NSNumber中尽量使用不可变的值。不要在NSArray 和NSDictionary中添加nil值会引起崩溃。
Preferred :
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018;
Not Preferred:
NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];NSNumber *buildingStreetNumber = [NSNumber numberWithInteger:10018];
常量
常量应该是静态的常量,不应该是#define 除非作为宏使用。
Perferred:
static NSString * const RWTAboutViewControllerCompanyName = @"RayWenderlich.com";
static CGFloat const RWTImageThumbnailHeight = 50.0;
Not Perferred:
#define CompanyName @"RayWenderlich.com"#define thumbnailHeight 2
枚举类型
For Example:
typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
RWTLeftMenuTopItemMain,
RWTLeftMenuTopItemShows,
RWTLeftMenuTopItemSchedule
};
你可以明确值的分配
typedef NS_ENUM(NSInteger, RWTGlobalConstants) {
RWTPinSizeMin = 1,
RWTPinSizeMax = 5,
RWTPinCountMin = 100,
RWTPinCountMax = 500,
};
Not Preferred:
enum GlobalConstants {
kMaxPinSize = 5,
kMaxPinCount = 500,
};
case 状态
当在switch中使用枚举类型,default是不需要的。
RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
case RWTLeftMenuTopItemMain:
// ...
break;
case RWTLeftMenuTopItemShows:
// ...
break;
case RWTLeftMenuTopItemSchedule:
// ...
break;
}
私有属性
私有属性应该在类的实现文件中的类扩展(匿名分类)中声明,命名分类(比如RWTPrivate或private)应该从不使用除非是扩展其他类。匿名分类应该通过使用<headerfile>+Private.h文件的命名规则暴露给测试。
@interface RWTDetailViewController ()
@property (strong, nonatomic) GADBannerView *googleAdView;
@property (strong, nonatomic) ADBannerView *iAdView;
@property (strong, nonatomic) UIWebView *adXWebView;
@end
布尔类型
Preferred:
if (someObject) {}
if (![anotherObject boolValue]) {}
Not Preferred:
if (someObject == nil) {}
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this.
如果BOOL属性的名字是一个形容词,属性就能忽略"is"前缀,但要指定get访问器的惯用名称。
@property (assign, getter=isEditable) BOOL editable;
条件语句
- 后面要加大括号
Preferred:
if (!error) {
return success;
}
Not Preferred:
if (!error)
return success;
or
if (!error) return success;
三目运算符
Preferred:
NSInteger value = 5;
result = (value != 0) ? x : y;
BOOL isHorizontal = YES;
result = isHorizontal ? x : y;
Not Preferred:
result = a > b ? x = c > d ? c : d : y;
初始化方法
- 返回类型是instancetype不是返回id。确保编译器正确判断推断结果。
- (instancetype)init {
self = [super init];
if (self) {
// ...
}
return self;
}
类构造方法
要求同上
@interface Airplane
+ (instancetype)airplaneWithType:(RWTAirplaneType)type;
@end
CGRect 方法
- 访问x,y,width或者height时使用CGGeometry来访问。
Preferred:
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
CGRect frame = CGRectMake(0.0, 0.0, width, height);
Not Preferred:
CGRect frame = self.view.frame;
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
CGRect frame = (CGRect){ .origin = CGPointZero, .size = frame.size };
Golden Path
Preferred:
- (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
}
Not Preferred:
- (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
错误处理
判断返回值而不是错误变量。
Preferred:
NSError *error;
if (![self trySomethingWithError:&error]) {
// Handle Error
}
Not Preferred:
NSError *error;
[self trySomethingWithError:&error];
if (error) {
// Handle Error
}
单例模式
- 使用线程安全方式创建实例。
+ (instancetype)sharedInstance {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
换行符
一行代码太长的话可以使用换行符,换成两行。
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
down
self.productsRequest = [[SKProductsRequest alloc]
initWithProductIdentifiers:productIdentifiers];
- 少用++ -- 运算符
- 规范只是建议不要拘泥
- 对于文章的大部分内容还是认同的,但是对于方法名(+/-)符号后添加空格,就个人而言感觉意义并不大。