object-c 编码规范与指导
文档版本
版本号 | 修改时间 | 修改内容 | 修改人 |
---|
概述
对于任何工程项目来说,统一的施工标准都是保证工程质量的重要因素。堪称当今人类最抽象、最复杂的工程—软件工程,自然更加不能例外。高品质、易维护的软件开发离不开清晰严格的编码规范。本文档详细描述object-C软件开发过程中的编码规范。本规范也适用于所有在文档中出现的源码。
文件结构
所有iphone的源文件均必须包含一个规范的说明,说明包含了该文件的名称、功能概述、作者、版权和版本历史信息等内容。文件头和函数的说明的格式为:
1.文件头说明
/*fileName
======================================================================
模块名 :<模块名称>
文件名 :<文件名>
实现功能:<描述该文件实现的主要功能>
作者 :<作者部门和姓名>
版本 :<当前版本号>
创建日期:
备注 :<其它说明>
修改日期:<日期格式:yyyy-mm-dd>
修改人 :<修改人>
修改内容:<修改内容>
======================================================================
fileName*/
2.方法说明
/**
* <#Description#>
*
* @param task <#task description#>
* @param arrange <#arrange description#>
*
* @created by 谢躜 on 2015-01-21 09:30:19
*/
3.头文件的引用说明
在h文件中引用其他类用@class fileName
;
在m文件中引用其他类都用#import “fileName.h
”
4.文件的组织结构
参考 coding ios 客户端源码规范
├── Coding_iOS
│ ├── Models:数据类
│ ├── Views:视图类
│ │ ├── CCell:所有的CollectionViewCell都在这里
│ │ ├── Cell:所有的TableViewCell都在这里
│ │ └── XXX:ListView(项目、动态、任务、讨论、文档、代码)和InputView(用于聊天和评论的输入框)
│ ├── Controllers:控制器,对应app中的各个页面
│ │ ├── Login:登录页面
│ │ ├── RootControllers:登录后的根页面
│ │ ├── MeSetting:设置信息页面
│ │ └── XXX:其它页面
│ ├── Images:app中用到的所有的图片都在这里
│ ├── Resources:资源文件
│ ├── Util:一些常用控件和Category、Manager之类
│ │ ├── Common
│ │ ├── Manager
│ │ ├── OC_Category
│ │ └── ObjcRuntime
│ └── Vendor:用到的一些第三方类库,一般都有改动
│ ├── AFNetworking
│ ├── AGEmojiKeyboard
│ ├── ASProgressPopUpView
│ ├── ActionSheetPicker
│ ├── FontAwesome+iOS
│ ├── MJPhotoBrowser
│ ├── MLEmojiLabel
│ ├── NSDate+Helper
│ ├── NSStringEmojize
│ ├── PPiAwesomeButton
│ ├── QBImagePickerController
│ ├── RDVTabBarController
│ ├── SMPageControl
│ ├── SVPullToRefresh
│ ├── SWTableViewCell
│ ├── UMENG
│ ├── UMessage_Sdk_1.1.0
│ ├── XGPush
│ ├── XTSegmentControl
│ └── iCarousel
└── Pods:项目使用了[CocoaPods](http://code4app.com/article/cocoapods-install-usage)这个类库管理工具
命名规则
如果想要有效的管理一个稍微复杂一点的体系,针对其中事物的一套统一、带层次结构、清晰明了的命名准则就是必不可少而且非常好用的工具。
活跃在生物学、化学、军队、监狱、黑社会、恐怖组织等各个领域内的大量有识先辈们都曾经无数次地以实际行动证明了以上公理的正确性。除了上帝(设它可以改变世间万物的秩序)以外,相信没人有实力对它不屑一顾。
在软件开发这一高度抽象而且十分复杂的活动中,命名规则的重要性更显得尤为突出。一套定义良好并且完整的、在整个项目中统一使用的命名规范将大大提升源代码的可读性和软件的可维护性。
在引入细节之前,先说明一下命名规范的整体原则:
-
同一性:
在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。 -
标识符组成:
标识符采用英文单词或其组合,应当直观且可以拼读,可望文知意,用词应当准确。 -
最小化长度和最大化信息量原则:
在保持一个标识符意思明确的同时,应当尽量缩短其长度。 -
避免过于相似:
不要出现仅靠大小写区分的相似的标识符,例如i
与I
,function
与Function
等等。 -
避免在不同级别的作用域中重名:
程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。 -
正确命名具有互斥意义的标识符:
用正确的反义词组命名具有互斥意义的标识符,如:minValueInteger
和maxValueInteger
,getName()
和setName()
等
5. h,m,nib文件名命名
除了异常类等个别情况(不希望被用户看作一个普通的、正常的类之情况)外,iphone的h,m,nib文件名命名应该遵循以下准则:
(1) h,m,nib文件名命名的名称都要以大写字母开头;
(2) 如果是一般的视图控制器,则后面加上ViewController,即h,m,nib
文件名的名称仿效分别为:
***ViewController.h
***ViewController.m
***ViewController.xib
(3)如果是自定义的视图类,则后面加上对应的类型,
UITableViewCell 简写为 Cell,UICollectionViewCell 简写为CCell
h,m,nib文件名的名称仿效分别为:
***View.h、
***View.m、
***View.xib;
***Cell.h、
***Cell.m、
***Cell.xib;
***CCell.h、
***CCell.m、
***CCell.xib;
6. 变量
(1)所有变量名命名的名称都要以小写字母开头。
(2)类中定义变量名称:其主要格式为***+对象类所在的名称
,如给UITextFiled
命名,则要写成***TextField
、如valueTextFiled
、titleTextField
等,相应的UILabel
的命名有valueLabel
、titleLabel
等,UITableView
则要写成valueTableView
等。其规则也同样适用于NSArray、NSMutableDictonary
等所有类型;
另外,如果当前变量是自己类中使用,则要在后面加上下划线,如valueArray_等,而在属性中定义时用valueArray。
(3)全局变量全部以单词_global
开头,以类型结尾,如_global***TextField
、_global***String
等。
(4)成员变量。在变量前面加上下划线_
如
UIButon * _cancelButton;
(5)其中NSMutaleArray、NSMutableDictonary与NSArray、NSDictonary的结尾相同,分别为Array及Dict,不做区分。
7. 方法
(1)所有方法名命名的名称都要以小写字母开头,要求语义完整清晰,不要乱用简写。
(2) 在ViewController中,一个控件可能有多个事件 如果是事件的名称,则要先以对象名称加上对象的事件,如
UIButton *nameButton;
#program mark - Event
//默认情况下 EventTouchUpInside 我们简写成 Pressed
- (IBAction) nameButtonPressed:(id)sender;
//EventTouchDown
- (IBAction) nameButtonTouchDown:(id)sender;
(3) Action。 如果是在一个视图类中,一个控件的事件相对于这个视图类来说只是视图类的一个事件,则不需要以控件对像名称加上对像事件命名。 而是根据视图类来命名。
@interface AbstractActionSheetPicker : NSObject
@end
UIBarButtonItem *sysDoneButton = [self createButtonWithType:UIBarButtonSystemItemDone target:self
action:@selector(actionPickerDone:)];
UIBarButtonItem *sysCancelButton = [self createButtonWithType:UIBarButtonSystemItemCancel target:self
action:@selector(actionPickerCancel:)];
- (IBAction)actionPickerDone:(id)sender
{
}
- (IBAction)actionPickerCancel:(id)sender
{
}
8. 宏
宏全部用大写,并且用必要的下划线分开,如
#define NAME_VALUE @"dddd"
#define MAXSIZE 30
9. 常量
常量用字母 k 开头, 如
static const NSUInteger kUsernameRow = 0;
10. 代码风格
代码风格与版式代码风格的重要性怎么强调都不过分。一段稍长一点的无格式代码基本上就是不可读的。 先来看一下这方面的整体原则:
-
空行的使用
空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。所以不要舍不得用空行。 这里不做规定,视自己的风格而定 -
语句与代码行
一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。
“if”、“for”、“while”、“try”、“catch”等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 “{ }” 。这样可以防止书写和修改代码时出现失误。 -
缩进和对齐
程序的分界符 “{” 和 “}” 的格式如下所示:
while(1){
//statement
for(int i=0;i<=n;i++){
//statement
}
}
以上风格是约定风格,而下面风格则不提倡。
while(1)
{
//statement
for(int i=0;i<=n;i++)
{
//statement
}
}
“{ }” 之内的代码块在 “{” 右边一个制表符(4个半角空格符,直接按键盘上的Tab键来进行控制)处左对齐。
最大长度
代码行最大长度宜控制在80个字符以内。代码行不要过长,否则眼睛看不过来,也不便于打印。不过此规则可以视情况适当放宽。空格的使用
关键字之后要留空格。象NSInteger等关键字之后至少要留一个空格;
其余的不做要求,如for语句里面的几条语句、&&、||等。修饰符的位置
为便于理解,应当将修饰符 “*” 和 “&” 紧靠变量,例如NSString *testString
、NSArray *testArray
等注释
注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
注释应当准确、易懂,防止注释有二义性。错误的注释不但无益反而有害。
当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。对于业务逻辑,常用的枚举数据,或者代码对应的参数一定要有说明,如
/**
* 设置类型
*
* @param type 类型 0 公有,1 私有
*
* @created by 谢躜 on 2015-01-21 18:47:24
*/
- (void)setType:(NSInteger)type
{
if(0 == type){
//当类型为公有的时候
...
}else if (1 == type){
//当类型为私有的时候
...
}
}
11. h文件组织
类 interface h文件中分别依次列出属性,方法。
#import <UIKit/UIKit.h>
@interface DateilViewController : UIViewController
{
//变量
NSString *_dataString;
}
//属性
@property (nonatomic, strong) NSDictionary *supplyDateilDict;
@property (nonatomic, strong) NSMutableArray *supplyArray;
//方法
- (void)handleData;
- (void)createView;
@end
协议 protocol ,依次列出 @required
,@optional
和
@protocol UITableViewDataSource<NSObject>
@required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// Editing
// Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
// Index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#")
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
// Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// Data manipulation - reorder / moving support
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
@end
12. m文件组织
/*Class 的生命周期
* Class 生命周期回调方法放在最前面
*/
#pragma mark - Lifecircle
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
}
- (void)viewDidLoad
{
}
- (void)viewWillAppear:(BOOL)animated
{
}
- (void)viewDidDisappear:(BOOL)animated
{
}
- (void)didReceiveMemoryWarning
{
}
- (void)dealloc
{
}
/* 所有的控件事件放在生命周期后面
* 包括 Event ,Action,Notifation
* 如果是相近的方法用program mark 分类。排在一起。
*/
#pragma mark - Event
- (void)backAction
{
}
- (void)selectTabbarButton:(UIButton *)sender
{
}
+ (void)reachabilityChanged:(NSNotification *)note
{
}
#pragma mark KeyBoardNotify
- (void)keyboardWillChange:(NSNotification *)note
{
}
- (void)keyboardShowNotify:(NSNotification *)note
{
}
//键盘隐藏调整界面
- (void)keyboardHideNotify:(NSNotification *)note
{
}
/*其它方法分为两部分,
* 第一部分是数据模型操作相关的方法
* 第二部分为视图,控件相关操作
*/
#pragma mark - Fouction
#pragma mark - HandleModal
- (void)getSupplyDateilData
{
}
// 时间转换
- (NSString *)showTimeWithValue:(NSTimeInterval)time
{
}
//添加一个安排
- (void)addArrange
{
}
#pragma mark HandleView
- (void)creatDateilView
{
}
// 显示土地信息
- (void)creatDateilInformationView
{
}
- (void)createAdvertisementView
{
}
/*
* 其它协议,委托,数据源方法没有固定顺序,用到了就加到后面
*/
#pragma mark -UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
}
#pragma mark -UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
--