C语言iOS代码编程规范-根据项目更汇总

带动出几十个从零开始学iOS的实习生或试用期的开发人员后,觉得真的是宏观人数千面,每个人形容的代码都风格迥异,如果没一个文档规范,每次都和新娘进行口头的说法,大概自己是毫不敲代码了,所以吃了亏了即起编制iOS的编程规范。由于我于写iOS代码前直接是C语言的开,所以多正经都受C语言的熏陶。

编程规范.png

及大家分享下自家总的编程规范,有非正好的要大家指出(不过好能举例说明为何不好,并叫一个好之引进\_

1. 点规范

(1)首先是为人口编写程序,其次才是电脑。

软件之生命周期贯穿产品的支付,测试,生产,用户以,版本升级跟深维护等进程,只有爱读,易维护的软件代码才具备活力。

(2)保持代码的鲜明清晰,避免过度之编程技巧。

简简单单是太美。不要过度追求技术,否则会稳中有降程序的可读性。

(3)编程时首先达到对,其次考虑效率。

编程首先考虑的凡满足是,健壮性,可维护性,可移植性等质地因素。

(4)编写代码时得考虑到代码的而是测试性。

勿得以测试的代码是心有余而力不足维持质量之。实现统筹力量的同时,要供可以测试、验证的方。

(5)函数(方法)是也同一定功能而编写,不是万会工具箱。

方法是一个处理单元,是出于特定功能的,所以应当特别好地设计法,不可知是具有东西都置身一个艺术里实现。

(6)鼓励多注释。

当代码来变动时,注释一定要改,并且毫不添加多余或又的诠释。

2. 布局

程序布局的目的是现实来程序可以的逻辑结构,提高程序的准头、连续性、可读性、可维护性。统一的次布局与编程风格,有助于增强全项目之开发品质,提高支付效率,降低开发成本。

据统一之布局顺序书写头文件以及实现公文:

文件头注释
#import
文本里采用的巨大
常量定义
文本之中以的数据类型
全局变量
本地变量
类定义/实现

(1)If、else、else if、for、while、do等告知句自占一行,执行语句不得紧跟其后,不论执行报告句有些许都使加{}。

“{”前面添加一个空格,紧跟语句后。方法(函数)时,“{”另打一行并独
占一实施写。

if ( numberA > numberB ) {
    return numberA;
}

(2)定义指针类型的变量,“*****” 应该放在变量前。

NSString *str1 = @"Hello World!";

(3)源代码中提到较为紧密的代码应尽可能相邻。

CGFloat fWidth;
CGFloat fLength;
CGFloat fHeight;

(4)禁止以TAB键,必须运用空格进行缩进,缩进为4单空格。

在Xcode->Preferences->Text Editing->Indentation->Prefer
indent using中,将价值设置为Spaces。

(5)程序的交界符“{”和“}”在if、else、else if、for、while、do等语句时,“{”前补加空格紧跟语句后。在术(函数)应把一行又在同一列,同时和援他们的讲话对齐。“{}”之内的代码块下缩进规则对共同。

- (void)dealloc
{
    // Do Something
}

if (isUpdated) {
        // Do Something
}

(6)相关的赋值语句等号对联合。

promotionsEntity.promotionImageStr   = activityItemDict[@"promotion_image"];
promotionsEntity.promotionIdNum      = activityItemDict[@"promotion_id"];
promotionsEntity.promotionNameStr    = activityItemDict[@"promotion_name"];
promotionsEntity.promotionColorStr   = activityItemDict[@"promotion_color"];

(7)在switch语句被,每一个case分支和default要用“{}”括起来,“{}”中的始末需要缩进。

(8)函数(方法)块之间以一个空行分隔。

(9)一冠操作符如!、~、++、–、*、&、和[]、.、->、前后未加空格。

!bValue
~iValue
++iCount
*strSource
&fSum

(10)多最先运算符和她俩的操作数之间起码需一个空格。

fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;

(11)关键字之后要留住空格。“(”后以及“)”前 不添加空格。

if、for、while等根本字后应留一个空格再和左括哀号”(”。

if (0 == fWidth)

(12)方法名以及形参不可知留住空格,返回路和艺术标识符有一个空格。

措施名后紧跟”:”,然后紧跟形参,返回路”(”与”-”之间发生一个空格。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

(13)注释符与注释内容之间一旦因此一个空格进行分割。

/* 设置Frame的值 */
// TO DO

(14)长表达式(超过80排)要于低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分来底新行要拓展适量地缩进,使排版整齐。

if ( 0 == fWidth
    || 0 < fLength )

(15)函数(方法)声明时,类型和名不同意分行书写。

- (void)didReceiveMemoryWarning

(16)类吃功能模块以#pragma mark – 分割,上空两尽,下空一行

#pragma mark – UITextFieldDelegate

(17)方法实现时,参数过长则每个参数用同样履行,以冒号对旅。

- (void)doSomethingWith:(NSString *)theFoo
                   rect:(CGRect)theRect
               interval:(CGFloat)theInterval
{

假如措施名于参数名短,则每个参数占用一行,至少缩进4个字符,且为垂直对伙同(非冒号对伙同)。

- (void)short:(NSString *)theFoot
    longKeyword:(CGRect)theRect
    evenLongerkeyword:(float)theInterval
{
}

(18)方法调用沿用声明方法的习惯。

当和一行

[self doSomethingWith:@"test" rect:self.view.frame interval:1.0f];

要 冒号对共同

[self doSomethingWith:@"test"
                 rect:self.view.frame
             interval:1.0f];

(19)@public 和 @private 使用单独一履,且缩进1只字符

(20)Protocals声明中列标识符、代理名称、尖括号间不留空格。

id<MyProtocalDelegate> delegate;

于接近声明遭带有多个protocal,每个protocal占用一行,缩进2单字符。

@interface CustomBackButtonViewController () <UITextFieldDelegate,
  MyProtocalDelegate,
  UITabBarControllerDelegate,
  UITabBarDelegate>

呢可与第一独针对伙同,保持清晰易读

@interface ShopViewController () <UIGestureRecognizerDelegate,
                                  HXSClickEventDelegate,
                                  UITableViewDelegate,
                                  UITableViewDataSource>

假若不用所有办法都是必须得,使用@optional标示。

(21)UIViewController.m的文件布局,不同变量和章程的先后顺序:

<1>#import “LocationCustomButton.h”

尽开始是导入需要动用及之另class头文件,头文件按类别分类

// controller
#import “TextSelectionViewController.h"
// model
#import "PayPasswordUpdateModel.h"
#import "WalletModel.h"
// views
#import "PayPasswordAlertView.h"
<2>#define KEY_BANK_TAIL @“bank_tail"

添加宏定义,将在文件中需利用及的常量,字符串等之所以宏定义。

<3>@property (nonatomic, strong) NSArray *bankCardList;

property的性质定义。不用拿需以的methods声明,在iOS7继Methods已经休待先声明又使用了。

<4>- (void)viewDidLoad

#pragma mark - Life Cycle 添加生命周期的方法

- (void)viewWillAppear:(BOOL)animated
 - (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
-(void)viewDidDisappear:(BOOL)animated
- (void)didReceiveMemoryWarning
- (void)dealloc
<5>#pragma mark - override

重载父类的法子

<6>#pragma mark - Intial Methods

初始化的办法,如

- (void)initialNavigationBar
- (void)initialTableView
<7>#pragma mark - Target Methods

点击事件或通知事件

<8>#pragma mark - UITextFieldDelegate

Delegate的轩然大波,将兼具的delegate放在和一个pragma下

<9>#pragma mark - Setter Getter Methods

持有的property使用懒加载,并以setter或getter放在脚,不影响工作代码的翻阅。

<10>#pragma mark - private method

私方法的代码尽量抽取创建公共class。

3. 注释

(1)多尽注释采用”/* … */”, 单行注释采用 “// …”.

(2)一般情形下,源程序有效注释量必须以30%上述。

诠释语言不宜太多为非可知无限少,注释语言必须规范、易懂、简洁。

(3)注释应与那讲述的代码相近,对代码的注释应在其上面或右手相邻位置,不可在下方,如放于上方则用跟那上面的代码用空行隔开。

(4)注释与所描述内容展开相同地缩排。

(5)文件最前面的笺注,是保存了工程自动生成的诠释,但是得展开如下修改:文件作者改也私有的名,公司叫吧Insigma Hengtian software Ltd. 如:

//
//  ViewController.m
//  test
//
//  Created by ArthurWang on 14-5-7.
//  Copyright (c) 2014年 Insigma HengTian Software Ltd. All rights reserved.
//

(6)类、协议、结构体注释。如:

/*
 @class HTServerDatamanager
 @abstract 异步连接服务器管理类
 @discussion 异步请求服务器,接收到响应后,通过回调把数据回传到对象
 */

(7)成员方法、接口注释。如:

/*
 @method  initWithTarget:selector:
 @abstract  类初始化函数
 @discussion  本类使用时必须调用此函数进行初始化
 @param target 响应回调对象
 @param selector  回调对象的selector
 @result   类对象
 */

4. 命名

(1)标识符要采用英文单词或该构成,便于记忆和看,切忌用汉语拼音来命名。

标识符应当直观且可以拼读,可望文知意,英文单词一般不要太复杂,用词应规范。

(2)严格禁止用连续的下划线,下划线为不能够出现于标识符头或最后。(实例变量和特种用法除外)

CGFloat variable__name;
NSString *variale___name;

(3)程序中永不出现不过因大小区别的形似之标识符。

NSString *contentOfView;
NSString *ContentOfView;

(4)宏、常量誉为都如使用好写字母,用生划线‘_’分割单词。

#define URL_GAIN_QUOTE_LIST @"/v1/quote/list"
#define URL_UPDATE_QUOTE_LIST @"/v1/quote/update"
#define URL_LOGIN   @"/v1/user/login”

(5)程序中有些变量不要和全局变量重名。

尽管有变量和全局变量的作用域不同而不会见生语法错误,但容易使人头误解。

(6)使用同样的前缀来分变量的作用域。

g_ 全局变量
s_ 模块内静态变量

(7)方法名用小写字母开头的单词组合而成。

方名力求清晰、明了、通过艺术名就可知判明方法的重点力量。方法名中不同含义字段之间并非为此生划线连接,而如拿每个字段的首字母大写以展示区分。

- (NSString *)descriptionWithLocale:(id)locale;

(8)尽量避免名字中出现数字编号,如Value1, Vlaue2等,除非逻辑上实在需要编号。

(9)声明实例变量,都使property。

无以接近声明和贯彻之“{”与“}”之间声明。

@interface LumberjackViewController ()
{
    NSArray *dataSource;  // 错误:
}

(10)类名(及其category 和protocal)的首字母大写,使用假名大写的款式分开单词。

5. 变量

变量、常量和数据类型是程序编制的基础,是直涉及及程序设计之输赢。

(1)一个变量有且只有生一个力量,尽量不要将一个变量用作多种用场。

一个变量只所以来表示一个一定功能,不要将一个变量作多用场。

(2)循环语句与判断语句被,不同意对另变量进行测算和赋值。

错误: if ( 100 > (fWidth = 50 * fLength) )

(3)宏定义中如果含有表达式或变量,表达式和变量必须用小括号括起来。

#define MY_MIN(A, B)   ((A)>(B)?(B):(A))

(4)宏名大写字母

(5)对于全局变量通过合并的函数访问。

(6)最好不用以告诉句子块内声明局部变量。

(7)系统常用类作实例变量声明时参加后缀:

UIViewController: VC                      UIImage: Img
UIImageView:ImagView                   UIView:View
UILabel: Lbl                                    UIButton:Btn
UINavigationBar:Nbar                     UIToolbar:Tbar
UISearchBar:Sbar                            UITextField:TextField
UITextView:TextView                      NSArray:Array
NSMutableArray:Marray                  NSDictionary:Dict
NSMutableDictionary:Mdict             NSString:Str
NSMutableString:MStr                     NSSet:Set
NSMutableSet:Mset

(8)属性声明严把权限,对无待外部修改的性能使用readonly。

(9)NSString使用copy而非retain。

在ARC中NSString的使用Strong与Copy的功能一样。

(10)CFType 使用@dynamic,禁止用@synthesize

(11)除非必须,使用nonatomic。

(12)定义NSArray和NSDictionary使用泛型,提高代码可读性和健壮性。

NSArray<NSString *> *testArr = [NSArray arrayWithObjects:@"Hello", @"world", nil];
NSDictionary<NSString *, NSNumber *> *dic = @{@"key":@(1), @"age":@(10)};

在* 符号前面都补加相同空格。

6. 表达式

表达式是报句子的如出一辙有的,他们是不可分割的。

(1)一长条告句子只就一个功能。

复杂的口舌阅读起来,难被了解,并易隐含错误。

(2)在表达式中以括号,使表达式的运算顺序更清。

鉴于拿运算符的优先级与结合律熟记是比较不方便的,为了防止产生歧义并提高可读性,即使不加括号时运算顺序不会见转移,也当用括号确定表达式的操作顺序。

if ( (( 0 == iYear%4 ) && ( 0 != iYear%100 )) || ( 0 == iYear%400 ) )

(3)避免表达式中之增大功能,不要编写太复杂的复合表达式。

错误:int iResult = iYear++-++iMonth+iDay++;

(4)不可将布尔变量和逻辑表达式直接与YES、NO或则1、0开展比。

if (isSuccess)   //真
if (!isSuccess)  //假

(5)在准判断语句被,当整型变量与0比较时,不可模仿布尔变量的风骨,应当以整型变量用“==”或“!=”直接与0比较。

if (0 == iYear)
if ( 0 != iMonth )

(6)应当将指针变量用“==”或“!=”与nil比较。

指南针变量的零值是“空”(即nil),nil的价与0相同,但是两岸含义不同。

if ( nil == strName )

(7)在switch语句被,每一个case分支必须使break结尾,最后一个拨出必须是default分支。

避免漏掉break语句造成程序错误,同时保障程序简洁。对于多单分支相同处理的情形好合用一个break,但是只要就此注释加以证明。

(8)不可在for循环内修改循环变量,防止for循环失去控制。

(9)循环嵌套次数不浮3不好。

(10)do while 语句和while语句仅以一个尺码。

(11)如果循环体内设有逻辑判断,并且循环次数很特别,宜用逻辑判断移到循环体的外面。

(12)for语句之巡回控制变量的取值采用“半开头半闭区间”写法。

诸如此类做重新能够适应数组的特征,数组的下标属于一个“半初步半闭区间”。

int iMax[1000];
for (int i = 0; i < 1000; i++)
{
    NSLog(@"%d", iMax[i]);
}

(13)将int值转换为BOOL时承诺特别小心。

(14)OC中,BOOL被定义也unsigned char,这表示除去YES(1)和NO(0)外它还得是另外价值。禁止用int直接换为BOOL。

(15)将整型值转换为BOOL的方:使用三首运算符返回YES/NO,或以&&,||。

(16)BOOL、_BOOL和bool之间的变是平安之,但是BOOL和Boolean间的更换不是高枕无忧之,所以用Boolean堪称整型值。

(17)在OC中,只允许以BOOL。

7. 函数

(1)方法无克吧多只目的服务。

一个智一个功能。

(2)在接口中该尽可能少用外部定义的型(减少耦合)。

(3)避免函数有太多之参数,参数个数尽量控制以5个里面。

若果参数的确较多,不妨把这些参数定义成一个布局(或一个类)。

(4)对于生返回值的函数(方法),每一个旁都必须发返回值。

为确保对给调用函数返回值的判断,有返回值的函数中都各一个退出点还用发出返回值。

(5)对输入参数的不易和行之有效进行反省。

过剩主次不当以及倒是由于非法参数引起的。

(6)防止以函数(方法)的参数作为工作变量。

拿函数的参数作为工作变量,有或错误地转移参数内容。对要转的参数,最好先用部分变量代的,最后又用该有变量的情予以给该参数。

(7)函数(方法)体的面不能够最好怪,尽量控制以200实践内。

没完没了的函数不便宜调试,可读性差。

(8)禁止直接调用NSObject的类方法+new,也休想当子类中重载它。使用alloc和init方法。

(9)创建对象时尽可能以autorelease,创建临时对象时,尽量以于跟一行中autorelease掉,而未下单独的release语句。

(10)Dealloc的各个要跟变量声明的依次相同。

诸如此类好review代码。
倘若dealloc中调用其他措施来release变量,将让release的变量以注释的花样标注清楚。
先release自身成员变量,再调用父类dealloc方法。

8. 头文件

(1)申明成员类,应该引用该类申明,而未是富含该类的头文件。

@class MyViewController;
@interface ViewController : UIViewController
{
    MyViewController *_myViewController;
}

(2)共同的接口、结构体、常量和数据类型要定义在和一个头文件里。

(3)使用#import引入OC和OC++头文件,使用#include引入c和c++头文件。

9. 可靠性

呢保险代码的可靠性,编程时请遵循如下基本条件,优先级递减:
正确性
稳定性
然测试性
规范/可读性
全局效率
片效率
私家表达方式/个人方便性

(1)防止内存操作越界

内存操作主要是乘对数组、指针、内存地址等得操作,内存操作越界是软件系统重点错误有,后果往往深严重,引起崩溃。

(2)当变量释放后,需要将变量置为nil。

避免因野指针引起的主次崩溃。

(3)变量在利用前答应初始化,防止不初始化的变量被引述。

引用未初始化的变量,会滋生程序的倒台。

(4)指针类型变量必须初始化为nil。

(5)指针不要进行复杂的逻辑或算术操作。

经复杂的逻辑或算术操作后,指针的职位就充分为难确定。

(6)减少指针和数据类型的强制类型转化。

强制类型转化而类型强转错误会引起崩溃。

(7)对变量进行赋值时,必须对其价值进行合法性检查,防止越界等情景来。

(8)非初始化方法吃的alloc操作前要使nil判断。

(9)在编写派生类的赋值时,主要不苟忘记对基类的成员变量重新赋值。

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

(10)私有方法应该当落实文件中阐明。

@interface ViewController ()
- (void)login;
@end

10. 断言

预言是指向某种假要标准进行反省,可以快捷发现并稳定软件文件,同时针对系统错误进行自动报警。

(1)整个软件系统应以统一的断言。

assert(str);

(2)正式软件出品被许诺拿断言和其它的调测代码去丢。

加速软件运行速度。

11. 其他

(1) 避免了多直接采用这数。

应该还下宏定义,采用这数不爱了解含义并容易失误。

(2) 枚举第一独分子要赋初始值。

(3) addObject之前要非空判断。

(4) release版本代码去丢NSLog打印,除了保留很分支的NSLog。

(5) 禁止在代码中一直写死字符串资源,必须要因此字符串ID替代。

该考虑多语言国际化,尽量以NSLocalizedStringFromTable实现对字符串ID的援。

(6) 对于框架设计,逻辑层尽量与UI层分离,降低耦合度。

(7) delegate对象下assign,禁止以retain。

因为retain会引起导致循环索引导与内存泄露,并且针对项目的内存泄露无法给Instrument发现,极难调试。

(8) Controller独立于View和Controller。

永不在View相关的近乎中上加了多的政工逻辑代码,这为代码的可是重用性很不同。Controller负责业务逻辑代码,且Controller的代码和View尽量无关。

(9)init方法及dealloc方法是最为常用之不二法门,所以用他们身处类实现之发端位置。

(10) 使用空格将同一的变量、属性对同,使用换行分组。

// END

小结写了了,复制黏贴好辛苦呀。发现多修以支付被还尚未遵循,因为急需变动实在太频繁了,并且要求的开时间莫过于太缺。吐槽下活组,能无克多着想多考虑然后听听我们付出的见解啊。!_!