# iOS 我的代码规范
[TOC]
***
# 命名部分
***
# 项目名
强迫症患者感觉不对的项目名:
MsAddressBook
Ms_AddressBook
MS_SDFAddressBook -前缀太长没有意义
msAddressBook
MS_AddressBook -这个说不上不对。
MSAddressBookTest -用test还是用demo呢?
总结下,大概遵守下列规则
- 前缀+描述性+功能(+Demo);如 MSSimpleRecordDemo
- 前缀大写;前缀最好是有意义的、简约的字母。
- 中间不使用下划线。
- 如果是Demo,则后缀使用Demo,不使用Test。
如:MSAddressBook,MSAddressBookDemo。
***
# 类名
看着不舒服的类名:
LiMakingVC
LiMyJLviewController --view 的首字母应该大写
Ky_GradeVc --前缀为什么要小写,要不要“_”
CardIconEditViewController --会不会太长
感觉正确的类名:
# 方法名
让人知道是哪个模块+哪个功能的
## { 到底换行,还是不换行
# 属性名字
# 扩展类
# 变量名字
# 宏定义
# 其他
## Masonry 中 leading 和 left不混用
leading 和 trailing 一起用,left 和 right 一起用,不混合搭配。
***
# 控制器内代码结构
分为几个层级
1、控制器生命周期方法
2、delegate方法
3、私有方法:网络请求、逻辑等
4、懒加载

***
# 语法部分
类型
使用到整形变量时,建议使用NSInteger NSUInteger,不建议使用int,uint 。
使用float时,建议使用CGFloat
常量
建议
static NSString *const PLMessageCountChanageNotificationName = @"MessageCountChanageNotification"
static NSUInteger const PLRetryMaxCount = 5
不建议
#define PLMessageCountChanageNotificationName @"MessageCountChanageNotification"
#define PLRetryMaxCount 5
变量
遵循驼峰模式即可
对于实例变量建议以下划线开始命名
@interface Foo() {
NSString *_name
}
@end
对于局部变量建议不要以下划线开头, 避免误解变量的作用域
不建议
- (void)uploadVideo {
NSString *_name = @"";
}
@end
字面值
对于NSString, NSDictionary, NSArray, 以及 NSNumber 支持语法糖
建议
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @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 *buildingStreetNumber = [NSNumber numberWithInteger:10018];
枚举
当使用 enum 的时候,建议使用新的固定的基础类型定义,因为它有更强大的类型检查和代码补全。 SDK 现在有一个 宏来鼓励和促进使用固定类型定义 - NS_ENUM()
建议
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear,
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
不建议
enum UIViewAnimationCurve {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear,
};
控制语句
关于if
一行代码:
条件语句体应该总是被大括号包围。尽管有时候你可以不使用大括号(比如,条件语句体只有一行内容),但是这样做会带来问题隐患。比如,增加一行代码时,你可能会误以为它是 if 语句体里面的。此外,更危险的是,如果把 if 后面的那行代码注释掉,之后的一行代码会成为 if 语句里的代码。
建议
if (!error) {
return success;
}
不建议
if (!error)
return success;
or
if (!error) return success;
多行代码:
在if中对于花括号{的处理应该趋于书写在行尾,这样控制条件和控制语句容易被视为一个整体。
建议
if(condition) {
//...
} else {
//...
}
不建议
if(condition)
{
//..
}
else
{
//..
}
尤达表达式
不要使用尤达表达式。尤达表达式是指,拿一个常量去和变量比较而不是拿变量去和常量比较。它就像是在表达 “蓝色是不是天空的颜色” 或者 “高个是不是这个男人的属性” 而不是 “天空是不是蓝的” 或者 “这个男人是不是高个子的”
推荐
if ([myValue isEqual:@42]) { ...
不推荐
if ([@42 isEqual:myValue]) { ...
多层嵌套
在使用条件语句编程时,不要嵌套 if 语句。使用多个 return 可以避免增加循环的复杂度,并提高代码的可读性。因为方法的重要部分没有嵌套在分支里面,并且你可以很清楚地找到相关的代码。
推荐
- (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
}
不推荐
- (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
复杂的表达式
当你有一个复杂的 if 子句的时候,你应该把它们提取出来赋给一个 BOOL 变量,这样可以让逻辑更清楚,而且让每个子句的意义体现出来。
推荐
BOOL nameContainsSwift = [sessionName containsString:@"Swift"];
BOOL isCurrentYear = [sessionDateCompontents year] == 2014;
BOOL isSwiftSession = nameContainsSwift && isCurrentYear;
if (isSwiftSession) {
// Do something very cool
}
关于switch
括号不是必须的,为了代码结构层次清晰,建议加上括号。
switch(condition){
case 1:
{
//one line or multi-line
}
break;
default:
break;
}
对于枚举类型的switch,可以不需要default
UIViewAnimationCurve curveType = UIViewAnimationCurveEaseInOut;
switch(curveType) {
case UIViewAnimationCurveEaseInOut:
{
}
break;
case UIViewAnimationCurveEaseIn:
{
}
break;
case UIViewAnimationCurveEaseOut:
{
}
break;
case UIViewAnimationCurveLinear:
{
}
break;
}
关于for循环
对于集合类型(array,set) 建议使用 enumerateObjectsUsingBlock
NSArray *nameArray = @[@"Kita","jonas"];
[nameArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//...
}];
其次可以选择for in 如果不需要索引的话
for(NSString *name in nameArray) {
//...
}
三目运算符
三目运算符 ? 应该只用在它能让代码更加清楚的地方。 一个条件语句的所有的变量应该是已经被求值了的。类似 if 语句,计算多个条件子句通常会让语句更加难以理解。或者可以把它们重构到实例变量里面。
推荐
result = a > b ? x : y;
不推荐
result = a > b ? x = c > d ? c : d : y;
属性
对于属性修饰符要全都指示出来,对于纯量类型默认是(atomic,assign),对于对象类型默认是(atomic,strong)。权限修饰符默认readwrite可以不写,一般情况下属性都是readwrite,对于只读属性需要写明readonly
对于有可变类型的类(NSString,NSArray,NSDictionary,NSSet) 建议使用copy,是因为有可能引用可变对象
建议
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) UIView *containerView;
不建议
@property(nonatomic,strong) NSString *name;
@property(nonatomic) UIView *containerView;
方法
方法类型(-/+)后需要空一格
建议
- (void)setTitle:(nullable NSString *)title forState:(UIControlState)state;
不建议
-(void)setTitle:(nullable NSString *)title forState:(UIControlState)state;
注释
文件注释
注释是代码可读性的关键,最好的代码应该自成文档。
其他注释(类注释,方法注释等)
xcode8 建议使用自带注释快捷键 command+option+/
代码结构组织
viewController类的建议
```
@property (nonatomic, strong) UITableView *tableView;
...
pragma mark - Life cycle (生命周期)
- (instancetype)init {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
- (void)dealloc {}
pragma mark - UITableViewDelegate (代理协议)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {}
...
pragma mark - LMFootViewButtonDelegate(代理协议)
-(void)footViewDidSelectedButton:(UIButton *)sender andIndex:(NSInteger)index andButtonTitle:(NSString *)titleText{}
...
pragma mark - IBActions(event response)
- (IBAction)submitData:(id)sender {}
...
pragma mark - Private Methods
- (void)privateMethod {}
...
pragma mark - Getter and Setter
- (NSString *)name;
- (void)setName:(NSString *)name;
```
使用CGRect函数
建议
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);
不建议
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 };
Tips
行宽
尽量保持在100以内,具体设置如下:
Xcode->Preferences->Text Editing->Page guide at column
***
# Pod部分
***
# 部分
***
# 部分
***
# 部分
