开发文档

移动端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首字母,遵循实际规则即可。)

控件名类型示例
UIViewControllerViewControllerCPXBaseViewController
UViewViewCPXBaseView
UITableViewTableViewCPXOrderTableView
UITableViewCellCellCPXOrderListCell
UIButtonButtonCPXSuccessButton
UILabelLabelCPXSuccessLabel
UIImageViewImgViewCPXGoodsImgView
UITextFieldTextFieldCPXNameTextField
UITextViewTextViewCPXSuggestTextView
常量

·宏:小写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:     LaplaceZhang@126.com
 
    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加上其他第三方工具辅助分析内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值