开发文档

移动端iOS开发规范文档

序言

  • 根据网上的一些OC编码规范整理归纳而成,为了利于项目维护以及规范开发,促进成员之间Code Review的效率

函数的书写

  • 方法长度建议不超过80行,如果方法太长可以考虑抽取其中一部分
  • 方法(-、+)和返回值前面的左括号间隔一个空格,方法参数直接间隔一个空格。每个方法结束后需间隔一行来书写新方法
- (void)applicationDidEnterBackground:(UIApplication *)application

- (void)applicationWillResignActive:(UIApplication *)application 
  • 如果一个函数有特别多的参数或者名称特别长,将其按照:来对齐分行显示
-(id)initWithModel:(IPCModle)model
       ConnectType:(IPCConnectType)connectType
        Resolution:(IPCResolution)resolution
          AuthName:(NSString *)authName
          Password:(NSString *)password
               MAC:(NSString *)mac
              AzIp:(NSString *)az_ip
             AzDns:(NSString *)az_dns
             Token:(NSString *)token
             Email:(NSString *)email
          Delegate:(id<IPCConnectHandlerDelegate>)delegate;

函数的调用

函数调用的格式和书写的差不多,可以按照函数的长短选择写在一行或者分成多行

//写在一行
[myObject doFooWith:arg1 name:arg2 error:arg3];
 
//分行写,按照 : 对齐
[myObject doFooWith:arg1
               name:arg2
              error:arg3];
 
//第一段名称过短的话后续可以进行缩进
[myObj short:arg1
          longKeyword:arg2
    evenLongerKeyword:arg3
                error:arg4];

闭包

  • block的右括号"}"应该和调用block那行代码的第一个非空字符对齐
  • block内的代码采用一个tab(四个空格的距离)的缩进
  • 如果block过于庞大,应该单独声明一个变量来使用
//分行书写的block,内部使用一个tab的缩进
[operation setCompletionBlock:^{
    [self.delegate newDataAvailable];
}];

//使用C语言API调用的block遵循同样的书写规则
dispatch_async(_fileIOQueue, ^{
    NSString* path = [self sessionFilePath];
    if (path) {
      // ...
    }
});

//庞大的block应该单独定义成变量使用
void (^largeBlock)(void) = ^{
    // ...
};
[_operationQueue addOperationWithBlock:largeBlock];

//在一个调用中使用多个block,通过进行一个tab缩进
[myObject doSomethingWith:arg1
    firstBlock:^(Foo *a) {
        // ...
    }
    secondBlock:^(Bar *b) {
        // ...
    }
];

命名规范

项目命名

·项目名都遵循大驼峰命名。例如:AoRiseProject

Bundle Identifier 命名

·Bundle Identifier:采用反域名命名规范,全部采用小写字母,以域名后缀+公司顶级域名+应用名形式命名,例如:com.rogrand.dianbangbang

类名

类的命名都遵循大驼峰命名。一般是:前缀 + 功能 + 类型。例如:CPX + Login + ViewController,在实际开发中,一般都会给工程中所有的类加上属于本工程的前缀
常用控件类命名类型对照表(下表中前缀为:CPX,如果用到下表中没有列举出来,请去掉UI首字母,遵循实际规则即可。)

控件名 类型 示例
UIViewController ViewController CPXBaseViewController
UView View CPXBaseView
UITableView TableView CPXOrderTableView
UITableViewCell Cell CPXOrderListCell
UIButton Button CPXSuccessButton
UILabel Label CPXSuccessLabel
UIImageView ImgView CPXGoodsImgView
UITextField TextField CPXNameTextField
UITextView TextView CPXSuggestTextView

常量

·宏:小写k+大驼峰 即为:#define kUserAgeKey @“ageKey”
·全局常量:工程前+缀全大写,下划线隔开 即为:extern const NSString MW_USER_AGE_KEY

清晰
  • 命名应该尽可能的清晰和简洁,但在Objective-C中,清晰比简洁更重要
//清晰
insertObject:atIndex:
//不清晰,insert的对象类型和at的位置属性没有说明
insert:at:
  • 不要使用单词的简写,拼写出完整的单词
//清晰
destinationSelection:setBackgroundColor:
 
//不清晰,不要使用简写
destSel:setBkgdColor:
  • 命名方法或者函数时要避免歧义
//有歧义,是返回sendPort还是send一个Port?
sendPort
 
//有歧义,是返回一个名字属性的值还是display一个name的动作?
displayName
  • 命名统一使用驼峰命名法;只采纳有广为人知含义的缩写,比如infomsgUIHTTP这类。自造的缩写不被认可。总体的命名原则是清晰和一致,避免歧义。

  • 类名需要结合项目名称来命名,确保整个项目中的自定义类的名称开头是统一的,同样要确保类名需要大写字母开头。

  • 类名命名需结合功能或者模块,并且尾部要带上该类的类型,比如
    UIViewController的子类命名为JasonIndexViewController。
    UIViewController 后缀添加“Controller”
    UIView 后缀添加“View”
    UIButton 后缀添加“Button"或者"Btn"
    UILabel 后缀添加“Label"

一致性

  • 整个工程的命名风格要保持一致性,最好和苹果SDK的代码保持统一。不同类中完成相似功能的方法应该叫一样的名字,比如我们总是用count来返回集合的个数,不能在A类中使用count而在B类中使用getNumber

命名方法

  • OC的命名方法通常比较长,是为了让程序有更好的可读性,目的是为了可以当成一个句子的形式朗读出来,达到见名知意的效果
  • 方法一般以小写字母打头,每一个后续的单词首字母大写,方法名中不应该有标点符号(包括下划线),有两个例外:
    • 可以用一些通用的大写字母缩写打头方法,比如PDF,TIFF等。
    • 可以用带下划线的前缀来命名私有方法或者类别中的方法。

如果方法表示让对象执行一个动作,使用动词打头来命名,注意不要使用dodoes这种多余的关键字,动词本身的暗示就足够了:

//动词打头的方法表示让对象执行一个动作
- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;

如果方法是为了获取对象的一个属性值,直接用属性名称来命名这个方法,注意不要添加get或者其他的动词前缀:

//正确,使用属性名来命名方法
- (NSSize)cellSize;
 
//错误,添加了多余的动词前缀
- (NSSize)calcCellSize;
- (NSSize)getCellSize;

对于有多个参数的方法,务必在每一个参数前都添加关键词,关键词应当清晰说明参数的作用:

//正确,保证每个参数都有关键词修饰
- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index
//错误,遗漏关键词
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
//正确
- (id)viewWithTag:(NSInteger)Tag;
//错误,关键词的作用不清晰
- (id)taggedView:(int)Tag;

不要用and来连接两个参数,通常and用来表示方法执行了两个相对独立的操作(从设计上来说,这时候应该拆分成两个独立的方法):

//错误,不要使用and来连接参数
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
//正确,使用and来表示两个相对独立的操作
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;

命名通知

通知常用于在模块间传递消息,所以通知要尽可能地表示出发生的事件,通知的命名方式是:

code[触发通知的类名] + [ Did | Will ] + [动作] + Notification

举个栗子

NSApplicationDidBecomeActiveNotification
NSWindowDidMiniaturizeNotification

注释

文件注释

  • 举个栗子
/*******************************************************************************
    Copyright (C), 2011-2013, Andrew Min Chang
 
    File name:  AMCCommonLib.h
    Author:     Andrew Chang (Zhang Min) 
    E-mail:     [email protected]
 
    Description:    
            This file provide some covenient tool in calling library tools. One can easily include 
        library headers he wants by declaring the corresponding macros. 
            I hope this file is not only a header, but also a useful Linux library note.
 
    History:
        2012-??-??: On about come date around middle of Year 2012, file created as "commonLib.h"
        2012-10-10: Change file name as "AMCCommonLib.h"
        2012-12-04: Add UDP support in AMC socket library
        2013-01-07: Add basic data type such as "sint8_t"
        2013-01-18: Add CFG_LIB_STR_NUM.
        2013-01-22: Add CFG_LIB_TIMER.
        2013-01-22: Remove CFG_LIB_DATA_TYPE because there is already AMCDataTypes.h
 
    Copyright information: 
            This file was intended to be under GPL protocol. However, I may use this library
        in my work as I am an employee. And my company may require me to keep it secret. 
        Therefore, this file is neither open source nor under GPL control. 
 
********************************************************************************/
/*************************************************************
 * Copyright (c)  成都魔力百聚科技有限公司
 * All rights reserved.
 *
 * 文件名称:        xxx
 * 文件标识:        xxx
 * 摘要说明:        xxx
 * 
 * 当前版本:        1.0.0
 * 作    者:       CPX
 * 更新日期:            
 * 整理修改:	
 *
 ***************************************************************/

文件注释的格式通常不作要求,能清晰易读就可以了,但在整个工程中风格要统一。

代码注释

  • 方法、函数、类、协议、类别的定义都需要注释,推荐采用Apple的标准注释风格,好处是可以在引用的地方alt+command+/点击自动弹出注释,非常方便
/**
 *  Get the COPY of cloud device with a given mac address.
 *
 *  @param macAddress Mac address of the device.
 *
 *  @return Instance of IPCCloudDevice.
 */
-(IPCCloudDevice *)getCloudDeviceWithMac:(NSString *)macAddress;
  • 协议、委托的注释要明确说明其被触发的条件
// 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;

####UI布局规范
·建议项目统一使用Masonryxib结合的方式布局。不允许出现直接设置frame的情况。如果是纯代码的项目,不允许出现xib和拉约束的情况。不允许storyboard开发。
· 提取方法,去除重复代码。对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。
· 尽可能的使用局部变量
· 尽量减少对变量的重复计算
· 尽量在合适的场合使用单例。使用单例可以减轻加载的负担,缩短加载的时间,提高加载效率。注意:并不是所有的地方都适用于单例

编码规范

  • 使用#pragma mark 来分类方法,参考以下结构,通常将不常用的函数方法写在底部,这里强制要求懒加载必须写在底部
#pragma mark – Life Cycle

#pragma mark - Events

#pragma mark – Private Methods

#pragma mark - UITextFieldDelegate

#pragma mark - UITableViewDataSource

#pragma mark - UITableViewDelegate

#pragma mark - Custom Delegates

#pragma mark – Getters and Setters

  • 枚举的定义参考系统定义枚举方式
typedef NS_ENUM(NSUInteger, UISearchBarStyle) {
    UISearchBarStyleDefault,    // currently UISearchBarStyleProminent
    UISearchBarStyleProminent,  // used my Mail, Messages and Contacts
    UISearchBarStyleMinimal     // used by Calendar, Notes and Music
}
  • ifcase语句,不论if或者else下有一个还是多个语句,都必须带上大括号。同样case语句也是如此。
//正确
if (!error) {
  return success;
}
//错误
if (!error)
  return success;
或  
if (!error) return success;
  • 布尔值推荐写法
if (someObject) {
    //...
}
if (![anotherObject boolValue]) {
    //...
}
  • 当需要提高代码的清晰性和简洁性时,三元操作符才会使用。
//推荐写法
NSInteger value = 5;
result = (value != 0) ? x : y;

BOOL isHorizontal = YES;
result = isHorizontal ? x : y;

//不推荐写法
result = a > b ? x = c > d ? c : d : y;
  • CGRect函数
//推荐写法
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

//不推荐的写法
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;
  • 当使用条件语句编码时,不要嵌套if语句,多个返回语句也是OK
//推荐写法
- (void)someMethod {
  if (![someOther boolValue]) {
    return;
  }

  //Do something important
}

//不推荐写法
- (void)someMethod {
  if ([someOther boolValue]) {
    //Do something important
  }
}

  • 单例模式
//单例对象应该使用线程安全模式来创建共享实例
+ (instancetype)sharedInstance {
  static id sharedInstance = nil;

  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedInstance = [[self alloc] init];
  });

  return sharedInstance;
}


资源文件规范

· 全部小写,采用下划线命名法,加前缀区分。所有的资源文件都需要加上工程前缀(小写形式)
· 命名模式:可加后缀_small表示小图,_big表示大图,逻辑名称可由多个单词加下划线组成,采用以下规则:
用途_模块名_逻辑名称
用途_模块名_颜色
用途_逻辑名称
用途_颜色

说明 前缀(工程前缀示例MW) 示例
按钮相关 mw_btn_ mw_btn_home_normal、mw_btn_red,mw_btn_red_big
背景相关 mw_bg_ mw_bg_home_header、mw_bg_main
图标相关 mw_icon_ mw_icon_home_location、mw_icon_input
分割线相关 mw_div_ mw_div_home_location、mw_div_input
默认相关 mw_def_ mw_def_home_location、mw_def_input

版本规范

· 采用A.B.C 三位数字命名,比如:1.0.2,当有版本更新的时候,依据下面的情况来确定版本号规范。

版本号 说明 示例
A.b.c 属于重大更新内容 1.0.0 -> 2.0.0
a.B.c 属于小部分更新内容 1.0.2 -> 1.2.2
a.b.C 属于补丁更新内容 1.0.2 -> 1.0.4

其他规范

· 检测内存泄漏。可使用Instruments加上其他第三方工具辅助分析内存。

你可能感兴趣的:(文档)