OC 代码规范简单整理

参考 禅与Objc编程艺术

命名

所有命名,必须英语规范。使用优秀的命名,代替或减少中文注释!!

类命名

  • 1 项目缩写大写打头
  • 2 按是否可以属于 整个项目 还是 某个模块 进行第二前缀的取舍。最后以父类或者其他结尾
  • 3 主要区分,公有类,私有类 的命名区分。
// 个人中心模块PersonCenter 有 设置界面Setting(设置界面属于整个项目唯一,而且可以脱离个人中心存在)
CZSettingViewController 而不需要 CZPersonCenterSettingViewController

// 产品模块 Product 有 产品详情界面 Detail 
CZProductDetailViewController 而不能 CZDetailViewController

NSString 等数据:直接命名英语

    NSString *name = @"";
    NSInteger age = 18;
    CGFloat money = 2.5;

NSArray / NSDictionary:使用负数形式,或者后缀Source

注:换行!
```
    NSArray *friends = @[@"张三",
                         @"李四"];

    NSDictionary *famaily = @{@"father":@"爸爸",
                              @"mother":@"妈妈"};
    

    NSMutableArray *tableSource = [@[@"section1",
                                     @"section2",
                                     @"section3"] mutableCopy];
    
    NSMutableDictionary *incomeTableSource = [@{@"key1":@"value1",
                                                @"key2":@"value2",
                                                @"key3":@"value3"} mutableCopy];
    
```

各种控件:全部添加后缀(label 除外)

注:禁止使用 view、label 等无意义的命名!

    // 用于赋值网络数据的不加后缀,用于本地显示的加后缀。命名一般参考接口!
    UILabel *nameLabel = [UILabel new]; // 不变的 
    UILabel *name = [UILabel new]; // 根据网络获取赋值的。
    UIButton *loginButton = [UIButton buttonWithType:UIButtonTypeSystem];
    UITextField *passwordField = [UITextField new];
    UIView *contentView = [UIView new];
    UITableView *productTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
等...

方法

根据返回与方法内容进行命名,之间多用 with、to、of、for 等连词连接。
命名尽量符合英语句子,达到不需要注释。

- (NSString *)substringWithRange:(NSRange)range;
- (BOOL)isEqualToString:(NSString *)aString;
- (NSRange)rangeOfString:(NSString *)searchString;
+ (NSTimeInterval)timeIntervalSinceReferenceDate;
+ (NSDate *)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;

- (void)addChildViewController:(UIViewController *)childController;

宏定义 与 常量

2 者选择性使用。

  • 常量,命名k打头,一般加上类名为第二前缀 ,保证名字唯一:尤其是提供外部使用的。
static NSString * const kProductTableName = @"testTabel";
static CGFloat const kContentViewLeftPadding = 20.;

// 或者.h.m 分开
FOUNDATION_EXTERN NSString *const kProductTableName;
NSString *const kProductTableName = @"testTabel";

// 参考 系统命名
UIKIT_EXTERN NSString *const UIKeyboardDidChangeFrameNotification;
UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification;
#define RGB(r,g,b)     [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.]

#define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending)
#define IOS9_OR_EARLIER !IOS9_OR_LATER

图片

使用 "_" 分割,不使用驼峰,命名与类的命名相似,最后需要加使用情景

navigation_back_icon
navigation_background

login_button_normal
login_button_selected

product_detail_basic_info_icon
product_detail_remark_icon

等...

格式

空格 与 换行

  • 1 属性
@property (nonatomic, copy) NSString *name;// 4个 空!
  • 2 赋值,计算,比较
self.title = @"首页";// 2个 空!
  • 3 方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    // do (内容上下不空行) 注意上面 3个 空!
}
  • 4 if - else
if (a == 0) {

    // do 上下 空一行

} else if (a == 1) {

    // do 上下 空一行

} else {
    // do 上 空一行,下 不空
}

注:行数小于3行,考虑美观,上下都不空行,注意空格!
  • 5 方法之间 空一行
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     return cell;
}
  • 6 方法内部 小模块 之间 空一行
- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.segmentView];
    [self.view addSubview:self.contentView];
    [self.segmentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.view).mas_offset(64);
        make.left.and.right.mas_equalTo(self.view);
        make.height.mas_equalTo(50);
    }];
    
    self.viewControllers = [NSMutableArray array];
    self.viewControllers = [@[self.detailViewController,
                             self.performanceViewController,
                             self.relatedDocumentViewController,
                             self.similarProductViewController] mutableCopy];
}
  • 7 所有多参数方法冒号对齐
- (void)loginWithEmployeeNo:(NSString *)employeeNo
                   orgCode:(NSString *)orgCode
             loginPassword:(NSString *)loginPassword
                   success:(ZJTClientManagerBlock)success
                   failure:(ZJTClientManagerBlock)failure {

}

类组织规范

  • 1每个类 不超过500,最好少于300(除 控件初始化 外布局代码,代码量会多一些,storyboard的就少)
#pragma mark - View lifeCycle

#pragma mark - Methods

#pragma mark - TableView Delegate

#pragma mark - Other Delegate

#pragma mark - Layout Views (处理UI布局,一般storyboard 不需要,代码布局会有大量,对应下面 Getter 也会大量)

#pragma mark - Getter Setter
  • 2 引入头文件,按照 系统框架,其他SDK,ViewController,View,Model 顺序添加。
#import "CZHomeViewController.h"
#import "CZAPPHeader.h"
#import <BaiduMapAPI_Map/BMKMapComponent.h>
#import "CZAViewController.h"
#import "CZBViewController.h"
#import "CZAView.h"
#import "CZBCell.h"
#import "CZAModel.h"
#import "CZBModel.h"
  • 3 接口 与属性:尽量,所有实例,都使用属性,并且使用懒加载方式初始化控件。
@interface CZHomeViewController ()
空!
@property (nonatomic, strong) UITableView *orderTableView;
@property (nonatomic, strong) NSMutableArray *dataSource;
空!
@end
  • 4 整理:在对View 传入ViewModel 后,对数据进行处理与赋值时,统一先处理数据,在统一赋值,分成2个小模块
-(void)bindViewModel:(id)model {

   // 可能model 返回的数据不能直接显示,所以先处理    
  
    // 然后统一赋值

}

// 其他地方类似,以免数据过于混乱
  • 5 待处理:在存在疑问或者未完成处,打warning (自己名字缩写如cz)然后描述内容,中英文即可(英文可以在warning区域直接看到)
#warning 

其他语法

  • 点语法 与 []:属性-点语法。方法-[]
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;
  • 多层嵌套:嵌套三层即以上,就应该考虑提出,按照上面集中处理,集中赋值的原则,应该合理应用嵌套。
 // 多层嵌套
    imageView.image = [[UIImage imageNamed:[self.dataSource objectAtIndex:2]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

// 拆分
    UIImage *currentAdImage = [UIImage imageNamed:[self.dataSource objectAtIndex:2]];
    imageView.image = [currentAdImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];