iOS开发中的命名规范

01/19/2017 09:40 上午 posted in  Program

关于命名

###统一要求
含义清楚,尽量做到不需要注释也能了解其作用,若做不到,就加注释
使用全称,不适用缩写

  1. 一般性原则
    可读性高(简洁且清晰)和防止命名冲突(通过加前缀后缀来保证)。Objective-C 的命名通常都比较长, 名称遵循驼峰式命名法. 一个好的命名标准很简单, 就是做到在开发者一看到名字时, 就能够懂得它的含义和使用方法. 另外, 每个模块都要加上自己的前缀, 前缀在编程接口中非常重要, 可以区分软件的功能范畴并防止不同文件或者类之间命名发生冲突, 比如相册模块(PhotoGallery)的代码都以PG作为前缀: PGAlbumViewController, PGDataManager.
代码 点评
insertObject:atIndex: Good
insert:at: 不清晰;要插⼊什么?“at”表⽰示什么?
removeObjectAtIndex: Good
removeObject: 不错,因为⽅法是⽤用来移除作为参数的对象
remove: 不清晰;要移除什么?
  1. 一致性
    尽可能与Cocoa.编程接⼝命名保持一致。如果你不太确定某个命名的⼀致性,请浏览头文件或参考文档中的范例,在使⽤多态方法的类中,命名的⼀致性⾮常重要。在不同类中实现相同功能的⽅法应该具有同的名称。
代码 点评
– (NSInteger)tag 在 NSView, NSCell, NSControl 中有定义
– (void)setStringValue:(NSString *) 在许多 Cocoa classes 中都有定义

###资源文件命名 (图片,本地化文件)

这个图片资源命名方式,以功能为组织形式,是一个很好的习惯,有利于查看资源文件。
原则:
1)采用单词全拼,或者大家公认无岐义的缩写(比如:nav,bg,btn等)
2)采用“模块+功能”命名法,模块分为公共模块、私有模块。公共模块主要包括统一的背景,导航条,标签,公共的按钮背景,公共的默认图等等;私有模块主要根据app的业务功能模块划分,比如用户中心,消息中心等。
例如用户中心用户头像图片的命名可以为:uc_imageview_user_icon

这部分规范可能是很有经验的设计提供,也有可能是我们开发人员提供,掌握总是没有坏处的。

我们的命名规则的基本思想是把文件名分成三部分,第一部分是图片的逻辑归属分类,第二部分是图片的表现内容,第三部分是图片的内容的类型,有些图片还会有第四部分,表示图片表现的状态。首先有几个规则是:

  • 用英文命名,不用拼音
  • 每一部分用下划线分隔
  • 图片名中两倍图在名字最后要加@2x,三倍图在名字最后要加@3x

###类的命名

类名(以及类别、协议名)应首字母大写,并以驼峰格式分割单词
大驼峰式命名:每个单词的首字母都采用大写字母
例子:MFHomePageViewController

  1. 类的前缀
    1)所有类名、枚举、结构、protocol定义时最好加一个统一的标示符,可以是项目缩写,或者个人项目的名称缩写,例如都加上全大写的Hoo(我的姓氏)作为前缀
    2)根据功能模块可以在给功能模块的类添加功能模块的名称前缀,如用户中心的profileViewController.可以命名为HooUCProfileViewController.
  2. 类的后缀
    所有protocol定义时,都加上后缀Delegate 。如,HooRefreshViewDelegate,表示RefreshView的协议;
    所有的控制器都加上Controller,所有的通知名都加上Notification。

ViewController: 使用ViewController做后缀
例子: MFHomeViewController

View: 使用View做后缀
例子: MFAlertView

UITableCell:使用Cell做后缀
例子: MFNewsCell

Protocol: 使用Delegate或者DataSource作为后缀
例子: UITableViewDelegate

UI控件依次类推

###类别命名
类名+标识+扩展(UIImageView +HP+Web)
例:如果我们想要创建一个基于UIImageView 的类别用于网络请求图片,我们应该把类别放到名字是UIImageView+HPWeb.h的文件里。UIImageView为要扩展的类名,HP为专属标识,Web为扩展的功能。

###方法命名
方法名应遵守小驼峰原则,首字母小写,其他单词首字母大写,每个空格分割的名称以动词开头。执行性的方法应该以动词开头,小写字母开头,返回性的方法应该以返回的内容开头,但之前不要加get。如:

- (void)insertModel:(id)model atIndex:(NSUInteger)atIndex;
- (instancetype)arrayWithArray:(NSArray *)array;

1.代理方法
以发送代理的对象类名作为代理方法名的开始(去掉类名的前缀,并且小写开头)

- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;

###私有变量
小驼峰式命名:第一个单词以小写字母开始,后面的单词的首字母全部大写
例子:firstName、lastName

以 _ 开头,第一个单词首字母小写
例子:NSString * _somePrivateVariable

私有变量放在 .m 文件中声明 

变量名使用小驼峰法, 使变量名尽量可以推测其用途属性具有描述性。别一心想着少打几个字母,让你的代码可以迅速被理解更加重要。每个属性命名都加上类型后缀,如,按钮就加上Button
后缀,模型就加上Model后缀。

@property (nonatomic, strong) UIButton *submitButton;

1)类成员变量名
  成员变量用小驼峰法命名并前缀下划线,如:

UIButton *_submitButton;

2)局部变量名
  遵守小驼峰命名规则,如:

NSInteger numCompletedConnections =3; 

###property变量

小驼峰式命名
例子:///注释
@property (nonatomic, copy) NSString *userName;

禁止使用synthesize关键词
###宏命名
全部大写,单词间用 _ 分隔。[不带参数]
例子: #define THIS_IS_AN_MACRO @"THIS_IS_AN_MACRO"

以字母 k 开头,后面遵循大驼峰命名。[不带参数]
例子:#define kWidth self.frame.size.width

小驼峰命名。[带参数]

#define getImageUrl(url) [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",kBaseUrl,url]]

###const常量

以小写k
开头,后面单词首字母大写,其余小写。如:

const float kMaxHeigt = 100.0f;

如果是特殊含义的常量也建议加上后缀,如通知加上Notification为后缀,如:

extern Nsstring * Const kLoginSuccessNotification

###Enum枚举的命名
Enum类型的命名与类的命名规则一致,以Objective-C的方式命名枚举
Enum中枚举内容的命名需要以该Enum类型名称开头
例子:

typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
};

###Delegate命名
类的实例必须为回调方法的参数之一, 如

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section

回调方法的参数只有类自己的情况,方法名要符合实际含义, 如:

- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView

以类的名字开头(回调方法存在两个以上参数的情况)以表明此方法是属于哪个类的, 如:

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

使用did和will通知Delegate已经发生的变化或将要发生的变化, 如:

- (NSIndexPath*)tableView:(UITableView*)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath;
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath;

##私有方法及变量声明
###声明位置
在.m文件中最上方,定义空的category进行声明
例子:

#import "CodeStandardViewController.h"
    // 在这个category(类目)中定义变量和方法
    @interface CodeStandardViewController (){
      // 声明私有变量
    }

     // 私有方法
    - (void)samplePrivateMethod;
    @end

    @implementation CodeStandardViewController
    // 私有方法的实现
    - (void)samplePrivateMethod{
      //some code
    }

##关于注释
代码中尽量少注释,让代码能自我描述。不过当需要注释的时候,能需要清除的解释某个代码块的含义和作用。注释应当保持最新,如果不必要请删除。

  • 最好的代码是不需要注释的 尽量通过合理的命名
  • 良好的代码把含义表达清楚 在必要的地方添加注释
  • 注释需要与代码同步更新
  • 如果做不到命名尽量的见名知意的话,就可以适当的添加一些注释或者mark
    ###属性注释
    例子:
    /// 学生
    @property (nonatomic, strong) Student *student;

###方法声明注释:

/** 
   * @brief 登录验证
   *
   * @param personId 用户名
   * @param password 密码
   * @param complete 执行完毕的block
   *
   * @return
   */
  + (void)loginWithPersonId:(NSString *)personId password:(NSString *)password complete:(void (^)(CheckLogon *result))complete;

###关于UI布局
 使用Interface Builder进行界面布局
 Xib文件的命名与其对应的.h文件保持相同
 Xib文件中控件的组织结构要合理,Xib文件中控件需要有合理的可读性强的命名,方便他人理解

##格式化代码
###指针 "*" 位置
 
定义一个对象时,指针 "*" 靠近变量
例子: NSString *userName;

###方法的声明和定义
在 - 、+ 和 返回值 之间留一个空格,方法名和第一个参数之间不留空格

- (id)initWithNibName:(NSString *)nibNameOrNilbundle:(NSBundle *)nibBundleOrNil
{...}

###代码缩进
使用 xcode 默认缩进,即 tab = 4空格
使用 xcode 中 re-indent 功能定期对代码格式进行整理
相同类型变量声明需要独行声明
例子:

CGFloatoringX = frame.origin.x;
CGFloatoringY = frame.origin.y;
CGFloatlineWidth = frame.size.width;

Method与Method之间空一行
例子:

#pragma mark - private methods
- (void)samplePrivateMethod
{...}

- (void)sampleForIf
{...}

###对method进行分组
使用 #pragma mark - 方式对类的方法进行分组
例子:

#pragma mark - private methods

  - (void)samplePrivateMethod
  {...}

  - (void)sampleForIf
  {...}

  - (void)sampleForWhile
  {...}
  
  - (void)sampleForSwitch
  {...}

  - (void)wrongExamples
  {...}

  #pragma mark - public methods
  - (void)samplePublicMethodWithParam:(NSString*)sampleParam
  {...}

  #pragma mark - life cycle methods
  - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  {...}

  - (void)viewDidLoad
  {...}

  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {...}

###大括号写法
对于类的method: 左括号跟在第一行后边(遵循苹果官方文档)
例子:

- (id)initWithNibName:(NSString *)nibNameOrNilbundle:(NSBundle *)nibBundleOrNil{
      self = [super initWithNibName:nibNameOrNil

      bundle:nibBundleOrNil];

      if (self) {
            // Custom initialization
        }

      return self;
}

- (void)sampleForIf{
    BOOL someCondition = YES;
    if(someCondition) {
        // do something here
    }
}
- (void)sampleForWhile{
    int i = 0;
    while (i < 10) {
        // do something here
        i = i + 1;
    }
}
- (void)sampleForSwitch{
    SampleEnum testEnum = SampleEnumTwo;
    switch(testEnum) {
        caseSampleEnumUndefined:{
            // do something
            break;
        }
        caseSampleEnumOne:{
            // do something
            break;
        }
        caseSampleEnumTwo:{
            // do something
            break;
        }
        default:{
            NSLog(@"WARNING: there is an enum type not handled properly!");
            break;
        }
    }

任何需要写大括号的部分,不得省略
错误示例:

- (void)wrongExamples{
    BOOLsomeCondition = YES;
    if (someCondition)
        NSLog(@"this is wrong!!!");
    while(someCondition)
        NSLog(@"this is wrong!!!");
}