自用的 Object-C 代码规范
一、条件语句
1.1 使用 {}
将条件语句体包围
- 推荐
if (error) {
return @"错误";
}
- 不推荐
if (error)
{
return @"错误";
}
if (error)
return @"错误";
if (error) return @"错误";
1.2 用变量与常量比较,不要倒装
- 推荐
if (index == 20) {
...
}
- 不推荐
if (20 == index) {
...
}
1.3 nil 和 BOOL 使用 ! 作为运算符
- 推荐
if (!myObject) {
...
}
- 不推荐
if (myObject == nil) {
...
}
if (nil == myObject) {
...
}
1.4 提前 return,不要嵌套 if 语句
- 推荐
- (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
}
- 不推荐
- (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
1.5 复杂条件拆分变量,不要写在 if 条件里
- 推荐
BOOL nameContainsSwift = [sessionName containsString:@"Swift"];
BOOL isCurrentYear = [sessionDateCompontents year] == 2014;
BOOL isSwiftSession = nameContainsSwift && isCurrentYear;
if (isSwiftSession) {
// Do something very cool
}
- 不推荐
if ([sessionName containsString:@"Swift"] && ([sessionDateCompontents year] == 2014)) {
// Do something very cool
}
1.6 复杂三元运算符拆分变量,不要嵌套
- 推荐
result = a > b ? x : y;
- 不推荐
result = a > b ? x = c > d ? c : d : y;
1.7 方法通过参数返回 error 引用的,检查方法返回值,而不是检查 error
- 推荐
NSError *error = nil;
BOOL result = [self trySomethingWithError:&error];
if (!result) {
// Handle Error
}
- 不推荐
NSError *error = nil;
[self trySomethingWithError:&error];
if (error) {
// Handle Error
}
二、Case 语句
2.1 统一加上括号(*)
- 推荐
switch (condition) {
case 1: {
// ...
break;
}
case 2: {
// ...
break;
}
case 3:{
// ...
break;
}
default: {
// ...
break;
}
}
- 不推荐
switch (condition) {
case 1:
// ...
break;
case 2:
// ...
break;
case 3:
// ...
break;
default:
// ...
break;
}
三、命名
3.1 推荐使用长的、描述性的方法和变量名
- 推荐
UIButton *settingsButton;
- 不推荐
UIButton *setBut;
3.2 常量,驼峰命名,并加相关类作前缀
- 推荐
static const NSTimeInterval ZOCSignInViewControllerFadeOutAnimationDuration = 0.4;
static NSString * const ZOCCacheControllerDidClearCacheNotification = @"ZOCCacheControllerDidClearCacheNotification";
static const CGFloat ZOCImageThumbnailHeight = 50.0f;
- 不推荐
static const NSTimeInterval fadeOutTime = 0.4;
#define CompanyName @"Apple Inc."
#define magicNumber 42
3.3 方法,参数都带有描述性关键词,整个方法读起来像句子
- 推荐
- (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;
- 不推荐
- (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.
3.4 字面值,使用快速创建的方式,不要写的复杂
- 推荐
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;
- 不推荐
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 *buildingZIPCode = [NSNumber numberWithInteger:10018];
四、Class 类
4.1 类名使用三个大写字母作前缀
- 推荐
ZOCNetworkClient
- 不推荐
NetworkClient
4.2 Initializer 使用依赖注入
- 推荐
@interface ZOCPerson
+ (instancetype)personWithName:(NSString *)name;
@end
- 不推荐
@interface ZOCPerson
@property (nonatomic, copy) NSString *personName;
@end
这里需要补充 designated initializer (指定初始化)相关知识
4.3 属性,使用修饰定义,可选懒加载
- 推荐
@property (nonatomic, assign) NSInteger page;
@property (nonatomic, assign) CGFloat amount;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSArray *list;// 需要用作可变数据使用时,必须是 copy(其他类似)
@property (nonatomic, strong) NSArray *list;
@property (nonatomic, strong) NSMutableArray *list;
默认属性 (atomic, readwrite, assign)
默认修饰 readwrite 不写,特殊需求时加入;
默认修饰 assign 虽然是默认,也统一写上;
五、Category 分类
5.1 方法名加小写前缀以及下划线
- 推荐
@interface NSDate (ZOCTimeExtensions)
- (NSString *)zoc_timeAgoShort;
@end
- 不推荐
@interface NSDate (ZOCTimeExtensions)
- (NSString *)timeAgoShort;
@end
六、Protocols 协议
任何在未来可复用的设计,无形当中可以提高代码质量,这也应该一直是程序员的追求。是否这样设计代码,就是大师和菜鸟的区别。
七、NSNotification 通知,通知名词定义成常量
- 推荐
// Foo.h
extern NSString * const ZOCFooDidBecomeBarNotification
// Foo.m
NSString * const ZOCFooDidBecomeBarNotification = @"ZOCFooDidBecomeBarNotification";
八、美化代码
8.1 空格
- 4个空格代替 Tab,Xcode 默认设置
方法的大括号和其他的大括号(if/else/switch/while 等) 总是在同一行开始,在新起一行结束。
推荐
if (user.isHappy) {
//Do something
}
else {
//Do something else
}
- 不推荐
if (user.isHappy)
{
//Do something
} else {
//Do something else
}
8.2 换行:使用 Xcode 默认(*)
8.3 空行:分类之间空一行
代码分类:函数体,条件,case,等
九、代码组织
9.1 代码块
- 代码块如果在闭合的圆括号内的话,会返回最后语句的值
- 感觉是个骚操作,并不是很推荐使用;
NSURL *url = ({
NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint];
[NSURL URLWithString:urlString];
});
9.2 Pragma
#pragma mark - Lifecycle
#pragma mark - Action
#pragma mark - Methods
#pragma mark - Delegate And DataSource
#pragma mark - Getter And Setter
9.3 自定义警告与错误
#warning [cz] <#descriptor#>
#error [cz] <#descriptor#>
9.4 文档
/**
title(一句话总结)
detail(详细说明)
@param index <#index description#>
@param length <#length description#>
*/
Xcode 10 快捷键【command + option + /】
十、其他自用
10.1 UI 类,统一使用完整名称,不要缩写
- 推荐
UILabel *nameLabel;
UIButton *loginButton;
UIImageView *avatarImageView;
UIView *contentView;
UIScrollView *detailScrollerView;
UITableView *orderTableView;
UITableViewCell *orderTableViewCell;
// 这个特殊处理,省略 View(参考苹果官方的 UIAlertController,不然实在是太长了,因为要加模块-功能前缀)
UIViewController *orderController;
除了 UIViewController 特殊处理,其余全部使用完整命名
- 不推荐
UILabel *nameLab;
UIButton *loginBtn;
UIImageView *avatarImgView;
UIView *contentV;
UIScrollView *detailScroller;
UITableView *orderTable;
UITableViewCell *orderCell;
// 这个特殊处理,省略 View(参考苹果官方的 UIAlertController,不然实在是太长了,因为要加模块-功能前缀)
UIViewController *orderVC;
10.2 数据类,按规定简写
- 推荐
// 通用规则:可变类型,使用 M 后缀
// 常用的 4 个,使用缩写:Str、Arr、Dic、AttStr
NSString *nameStr;
NSMutableString *nameStrM;
NSArray *nameArr;
NSMutableArray *nameArrM;
NSDictionary *nameDic;
NSMutableDictionary *nameDicM;
NSAttributedString *nameAttStr;
NSMutableAttributedString *nameAttStrM;
// 以下不常用的或者其他的,统一使用完整名称,不缩写
NSSet *nameSet;
NSMutableSet *nameSetM;
NSDate *nameDate;
NSData *nameData;
NSMutableData *nameDataM;