带出几十位从零开始学iOS的实习生或试用期的开发人员后,以为真的是千人千面,每一个人写的代码都风格迥异,若是没有一个文档规范,每次都和新人进行口头的说教,大概本身是不用敲代码了,因此吃了亏了就开始编写iOS的编程规范。因为本人在写iOS代码前一直是C语言的开发,因此不少规范都受C语言的影响。c++
与你们分享下我总结的编程规范,有不合适的请你们指出(最好能举例说明为什么很差,并给一个好的推荐)^_^编程
软件的生命周期贯穿产品的开发,测试,生产,用户使用,版本升级和后期维护等过程,只有易读,易维护的软件代码才具备生命力。数组
简单是最美。不要过度追求技巧,不然会下降程序的可读性。安全
编程首先考虑的是知足正确性,健壮性,可维护性,可移植性等质量因素。bash
不能够测试的代码是没法保障质量的。实现设计功能的同时,要提供能够测试、验证的方法。服务器
方法是一个处理单元,是由特定功能的,因此应该很好地规划方法,不能是全部东西都放在一个方法里实现。app
当代码有改动时,注释必定要修改,而且不要添加多余或重复的注释。框架
程序布局的目的是现实出程序良好的逻辑结构,提升程序的准确性、连续性、可读性、可维护性。统一的程序布局和编程风格,有助于提升整个项目的开发质量,提升开发效率,下降开发成本。异步
遵循统一的布局顺序书写头文件和实现文件:ide
文件头注释 #import 文件内部使用的宏 常量定义 文件内部使用的数据类型 全局变量 本地变量 类定义/实现
“{”前面添加一个空格,紧跟语句后。方法(函数)时,“{”另起一行并独 占一行书写。
if ( numberA > numberB ) {
return numberA;
}
复制代码
NSString *str1 = @"Hello World!";
复制代码
CGFloat fWidth;
CGFloat fLength;
CGFloat fHeight;
复制代码
在Xcode->Preferences->Text Editing->Indentation->Prefer indent using中,将值设置为Spaces。
- (void)dealloc
{
// Do Something
}
if (isUpdated) {
// Do Something
}
复制代码
promotionsEntity.promotionImageStr = activityItemDict[@"promotion_image"];
promotionsEntity.promotionIdNum = activityItemDict[@"promotion_id"];
promotionsEntity.promotionNameStr = activityItemDict[@"promotion_name"];
promotionsEntity.promotionColorStr = activityItemDict[@"promotion_color"];
复制代码
!bValue
~iValue
++iCount
*strSource
&fSum
复制代码
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
复制代码
if、for、while等关键字以后应留一个空格再跟左括号”(”。
if (0 == fWidth)
复制代码
方法名后紧跟”:”,而后紧跟形参,返回类型”(”与”-”之间有一个空格。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
复制代码
/* 设置Frame的值 */
// TO DO
复制代码
if ( 0 == fWidth
|| 0 < fLength )
复制代码
- (void)didReceiveMemoryWarning
复制代码
#pragma mark – UITextFieldDelegate
复制代码
- (void)doSomethingWith:(NSString *)theFoo
rect:(CGRect)theRect
interval:(CGFloat)theInterval
{
复制代码
若是方法名比参数名短,则每一个参数占用一行,至少缩进4个字符,且为垂直对齐(非冒号对齐)。
- (void)short:(NSString *)theFoot
longKeyword:(CGRect)theRect
evenLongerkeyword:(float)theInterval
{
}
复制代码
在同一行
[self doSomethingWith:@"test" rect:self.view.frame interval:1.0f];
复制代码
或 冒号对齐
[self doSomethingWith:@"test"
rect:self.view.frame
interval:1.0f];
复制代码
id<MyProtocalDelegate> delegate;
复制代码
在类声明中包含多个protocal,每一个protocal占用一行,缩进2个字符。
@interface CustomBackButtonViewController () <UITextFieldDelegate,
MyProtocalDelegate,
UITabBarControllerDelegate,
UITabBarDelegate>
复制代码
也能够与第一个对齐,保持清晰易读
@interface ShopViewController () <UIGestureRecognizerDelegate,
HXSClickEventDelegate,
UITableViewDelegate,
UITableViewDataSource>
复制代码
若是并不是全部方法都是必须得,使用@optional标示。
#import “LocationCustomButton.h”
最开始是导入须要使用到的其余class头文件,头文件按类型分类
// controller
#import “TextSelectionViewController.h"
// model
#import "PayPasswordUpdateModel.h"
#import "WalletModel.h"
// views
#import "PayPasswordAlertView.h"
复制代码
#define KEY_BANK_TAIL @“bank_tail"
添加宏定义,将在文件中须要使用到的常量,字符串等用宏定义。
@property (nonatomic, strong) NSArray *bankCardList;
property的属性定义。不用将须要使用的methods声明,在iOS7后Methods已经不须要先声明再使用了。
- (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
复制代码
#pragma mark - override
重载父类的方法
#pragma mark - Intial Methods
初始化的方法,如
- (void)initialNavigationBar
- (void)initialTableView
复制代码
#pragma mark - Target Methods
点击事件或通知事件
#pragma mark - UITextFieldDelegate
Delegate的事件,将全部的delegate放在同一个pragma下
#pragma mark - Setter Getter Methods
全部的property使用懒加载,并将setter或getter放在底部,不影响业务代码的阅读。
#pragma mark - private method
私有方法的代码尽可能抽取建立公共class。
注释语言不宜太多也不能太少,注释语言必须准确、易懂、简洁。
//
// ViewController.m
// test
//
// Created by ArthurWang on 14-5-7.
// Copyright (c) 2014年 Insigma HengTian Software Ltd. All rights reserved.
//
复制代码
/*
@class HTServerDatamanager
@abstract 异步链接服务器管理类
@discussion 异步请求服务器,接收到响应后,经过回调把数据回传到对象
*/
复制代码
/*
@method initWithTarget:selector:
@abstract 类初始化函数
@discussion 本类使用时必须调用此函数进行初始化
@param target 响应回调对象
@param selector 回调对象的selector
@result 类对象
*/
复制代码
标识符应当直观且能够拼读,可望文知意,英文单词通常不要太复杂,用词应当准确。
CGFloat variable__name;
NSString *variale___name;
复制代码
NSString *contentOfView;
NSString *ContentOfView;
复制代码
#define URL_GAIN_QUOTE_LIST @"/v1/quote/list"
#define URL_UPDATE_QUOTE_LIST @"/v1/quote/update"
#define URL_LOGIN @"/v1/user/login”
复制代码
尽管局部变量和全局变量的做用域不一样而不会发生语法错误,但容易令人误解。
g_ 全局变量 s_ 模块内静态变量
方法名力求清晰、明了、经过方法名就可以判断方法的主要功能。方法名中不一样意义字段之间不要用下划线链接,而要把每一个字段的首字母大写以示区分。
- (NSString *)descriptionWithLocale:(id)locale;
复制代码
不在类声明和实现的“{”与“}”之间声明。
@interface LumberjackViewController ()
{
NSArray *dataSource; // 错误:
}
复制代码
变量、常量和数据类型是程序编写的基础,是直接关系到程序设计的成败。
一个变量只用来表示一个特定功能,不要把一个变量做多种用途。
错误: if ( 100 > (fWidth = 50 * fLength) )
#define MY_MIN(A, B) ((A)>(B)?(B):(A))
复制代码
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
复制代码
在ARC中NSString的使用Strong与Copy的效果同样。
NSArray<NSString *> *testArr = [NSArray arrayWithObjects:@"Hello", @"world", nil];
NSDictionary<NSString *, NSNumber *> *dic = @{@"key":@(1), @"age":@(10)};
复制代码
在* 符号前面都添加一空格。
表达式是语句的一部分,他们是不可分割的。
复杂的语句阅读起来,难于理解,并容易隐含错误。
因为将运算符的优先级与结合律熟记是比较困难的,为了防止产生歧义并提升可读性,即便不加括号时运算顺序不会改变,也应当用括号肯定表达式的操做顺序。
if ( (( 0 == iYear%4 ) && ( 0 != iYear%100 )) || ( 0 == iYear%400 ) )
复制代码
错误:int iResult = iYear++-++iMonth+iDay++;
if (isSuccess) //真
if (!isSuccess) //假
复制代码
if (0 == iYear)
if ( 0 != iMonth )
复制代码
指针变量的零值是“空”(即nil),nil的值与0相同,可是二者含义不一样。
if ( nil == strName )
复制代码
避免漏掉break语句形成程序错误,同时保持程序简洁。对于多个分支相同处理的状况能够共用一个break,可是要用注释加以说明。
这样作更能适应数组的特色,数组的下标属于一个“半开半闭区间”。
int iMax[1000];
for (int i = 0; i < 1000; i++)
{
NSLog(@"%d", iMax[i]);
}
复制代码
一个方法一个功能。
若是参数的确比较多,不妨把这些参数定义成一个结构(或一个类)。
为了保证对被调用函数返回值的判断,有返回值的函数中都每个退出点都须要有返回值。
不少程序错误和崩溃是由非法参数引发的。
将函数的参数做为工做变量,有可能错误地改变参数内容。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。
冗长的函数不利于调试,可读性差。
这样有利于review代码。 若是dealloc中调用其余方法来release变量,将被release的变量以注释的形式标注清楚。 先release自身成员变量,再调用父类dealloc方法。
@class MyViewController;
@interface ViewController : UIViewController
{
MyViewController *_myViewController;
}
复制代码
为保证代码的可靠性,编程时请遵循以下基本原则,优先级递减: 正确性 稳定性 可测试性 规范/可读性 全局效率 局部效率 我的表达方式/我的方便性
内存操做主要是指对数组、指针、内存地址等得操做,内存操做越界是软件系统主要错误之一,后果每每很是严重,引发崩溃。
避免由于野指针引发的程序崩溃。
引用未初始化的变量,会引发程序的崩溃。
经过复杂的逻辑或算术操做后,指针的位置就很难肯定。
强制类型转化若是类型强转错误会引发崩溃。
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
复制代码
@interface ViewController ()
- (void)login;
@end
复制代码
断言是对某种假设条件进行检查,能够快速发现并定位软件文件,同时对系统错误进行自动报警。
assert(str);
加快软件运行速度。
应该都使用宏定义,采用当即数不容易理解含义并容易出错。
应该考虑多语言国际化,尽可能使用NSLocalizedStringFromTable实现对字符串ID的引用。
由于retain会引发致使循环索引致使内存泄露,而且对类型的内存泄露没法被Instrument发现,极难调试。
不要在View相关的类中添加过多的业务逻辑代码,这让代码的可重用性不好。Controller负责业务逻辑代码,且Controller的代码与View尽可能无关。
// END
总结写完了,复制黏贴好累啊。发现不少条在开发中都没有遵照,由于需求变更实在太频繁了,而且要求的开发时间实在过短。吐槽下产品组,能不能多考虑多考虑而后听听咱们开发的意见啊。!_!