APP编码规范

前言

为什么要制定一套Objective-C在iOS APP开发的规范要求?我们都知道,一款APP开发出来之后,还有冗长的维护和迭代过程,而且在APP的开发过程中,绝大多数都是团队开发,如果在这期间没有一套统一、规范的开发标准,就很难保证代码风格的一致性,可读性降低 ,团队开发 和 后期维护 都会带比较严重的后果。
如果在APP的开发过程中都以这个标准去执行,代码的可读性、开发期间的沟通、后期维护都会非常顺畅。

开发标准(规范)制定依据

既然是标准,可能就会有人质疑了,你制定的这套标准有什么依据?
首先这个标准不是由个人制定,也不是由哪一个团队制定,而是根据Apple官方文档以及Xcode 中提供的一些SourceCode 为参考来制定的。
当然还有很多认可度极高的文档:

The Objective-C Programming Language
Cocoa Fundamentals Guid
Coding Guidelines for Cocoa
iOS App Programming Guide

规范正文

一 . 关于命名

命名要求含义清楚,尽量做到不需要注释也能了解其作用;
不要偷懒,勤加注释;
命名使用英语,不要使用拼音、数字

1. 类的命名

大驼峰式命名:每个单词的首字母都采用大写字母。
前缀以约定的标志性字母开头,中间以功能英文单词命名,再加上全名后缀(不得简写)。

例一:GTHomePageViewController  // Controller层控制器类名
例二:GTUserInfoModel  //Model层类名
例三:GTNewsListsTableViewCell  //View层TableViewCell的命名
例三:GTAlertSheetViewDelegate //代理方法中Delegate的命名
例三:GTAlertSheetViewDateSource //代理方法中DateSource的命名

2. Foundation成员变量的命名

小驼峰式命名:第一个单词以小写字母开始,后面的单词的首字母全部大写。

例一: .m 文件中声明的私有变量 
{
    NSString * _somePrivateVariable;
}
例二:property变量
@property (nonatomic, strong) NSString *userName;

3. UIKit成员变量的命名

小驼峰式命名:第一个单词以小写字母开始,后面的单词的首字母全部大写。此外命名必须是 描述性的单词+变量类型,一目了然。
变量类型运行使用通用的缩写,若缩写不是公认的,不推荐。

例一: .m 文件中声明的私有变量 
{
    UILabel * _nameLabel;
    UIButton * _nameBtn
}
例二:property变量
@property (nonatomic, strong) UILabel * nameLb;
@property (nonatomic, strong) UIButton * nameButton;

4. 宏命名

  • 情况一:全部大写,单词间用 _ 分隔。[不带参数] [不推荐使用]
  • 情况二:以字母 k 开头,后面遵循大驼峰命名。[不带参数]
  • 情况三:以字母 k 开头,小驼峰命名。[带参数]
    推荐 使用 [情况二][情况三]
例一:情况一
 #define THIS_IS_AN_MACRO @"THIS_IS_AN_MACRO"
例二:情况二
#define kWidth self.frame.size.width
例三:情况三
#define kGetImageUrl(url)  [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",kBaseUrl,url]]

5. Xib的命名

Xib文件的命名与其对应的.h文件保持相同

二. 枚举Enum

为什么要把枚举单独拿出来说?
我们都知道,代码中很多需要根据状态值来进行分类的,比如服务器传来一个状态参数1 、2、 3等等值,1代表交易成功、2代表已经付款、3代表未付款等等,这里我们在代码编写过程中直接用if else 来分类就low爆了,不仅代码的可读性低,而且维护起来非常不便。而且如果状态值代表的意义还有改变的,需要来怎么去处理?如果开发初期就规定使用枚举,这些问题就会很容易的解决。

  • 必须使用 NS_ENUM 或者 NS_OPTIONS
  • Enum类型的命名与类的命名规则一致
  • Enum中枚举内容的命名需要以该Enum类型名称开头
typedef NS_ENUM(NSUInteger, ShareUISelcetIndex) {
    ShareUISelcetIndexDefault = SSDKPlatformTypeUnknown, // 默认
    ShareUISelcetIndexWechatFriend = SSDKPlatformSubTypeWechatSession, // 微信好友
    ShareUISelcetIndexWechatGroup = SSDKPlatformSubTypeWechatTimeline, //微信朋友圈
    ShareUISelcetIndexQQFriend = SSDKPlatformSubTypeQQFriend, //QQ好友
    ShareUISelcetIndexQQZone = SSDKPlatformSubTypeQZone, //QQ空间
    ShareUISelcetIndexSina= SSDKPlatformTypeSinaWeibo, //新浪
    ShareUISelcetIndexRefresh, // 刷新
    ShareUISelcetIndexCopyToPad, // 复制到剪切板
};

三. 方法的命名

1.普通方法的命名

方法使用小驼峰法命名。
一个规范的方法读起来应该像一句完整的话(OC语言的风格)。读过之后便知函数的作用。
执行性的方法应该以动词开头,小写字母开头。
返回性的方法应该以返回的内容开头。

例一:执行性
-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
例二:返回性
-(instancetype)arrayWithArray:(NSArray *)array;

2.Delegate方法的命名

  • 类的实例必须为回调方法的参数之一;
  • 回调方法的参数只有类自己的情况,方法名要符合实际含义;
  • 以类的名字开头(回调方法存在两个以上参数的情况)以表明此方法是属于哪个类的;
  • 推荐使用did和will通知Delegate已经发生的变化或将要发生的变化.
类的实例必须为回调方法的参数之一
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section

回调方法的参数只有类自己的情况,方法名要符合实际含义;
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView

以类的名字开头(回调方法存在两个以上参数的情况)以表明此方法是属于哪个类的
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

推荐使用did和will通知Delegate已经发生的变化或将要发生的变化.
-(NSIndexPath*)tableView:(UITableView*)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath;
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath;

3. 对方法进行分组(#pragma mark -)

使用 #pragma mark - 方式对类的方法进行分组,会使代码分区,看起来非常赏心悦目。
如图:

image

4. 代码缩进

[小技巧]直接强文件中的代码剪切,再复制粘贴进来。 Xcode 会自动对代码进行缩进处理。
Method与Method之间至少空一行,最好是最多也只空一行。

5. 大括号写法

  • 左括号跟在第一行后边
  • 任何需要写大括号的部分,不得省略

错误示例:

- (void)wrongExample{
    BOOL someCondition = YES;
    if (someCondition)
        NSLog(@"this is wrong!!!");
}

规范示例:

- (void)rightExample{
    BOOL someCondition = YES;
    if (someCondition){
        NSLog(@"this is wrong!!!");
    }
}

四. 注释

1. 属性注释

  • 推荐使用 注释统一采用文档注释方式:/** description */ ,即Xcode 8 提供的快捷键注释。Xcode 7 版本采用这种注释在调用该属性的时候,会提示出这个描述,但现在Xcode 8 似乎没有。
  • 其他注释 // Description
@interface ShareUIView : UIView
/**
 block one 
 */
@property (nonatomic,copy) void(^cellClickblock)(ShareUISelcetIndex index);
@property (nonatomic,copy) void(^cellPushblock)(ShareUISelcetIndex index); // block two

@end

2. 方法声明注释

  • 推荐使用 Xcode 8 提供的快捷键注释。
/**
 单例模式
 *
 @return 单例对象
 */
+(LeeAlertSheetView *)sharedInstacne;

/**
 *  创建提示框(Alert 可变参数版)
 *
 *  @param title        标题
 *  @param message      提示内容
 *  @param cancelTitle  取消按钮(无操作,为nil则只显示一个按钮)
 *  @param vc           VC iOS8及其以后会用到
 *  @param confirm      点击按钮的回调(取消按钮的Index是cancelIndex -1)
 *  @param buttonTitles 按钮(为nil,默认为"确定",传参数时必须以nil结尾,否则会崩溃)
 */
- (void)showAlert:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ... NS_REQUIRES_NIL_TERMINATION;

五. 三目运算符

我们直接就开始举个栗子了

- (void)rightExample{
    BOOL someCondition = YES;
    if (someCondition){
        self.myView.alpha = 0.5;   
    }else{
        self.myView.alpha = 0.1;
   }
}

这里如果用三目运算符怎么写?

- (void)rightExample{
    self.myView.alpha = someCondition ? 0.5: 0.1
}

六. 多使用常量(const),代替宏(define)

可以参考这篇文章iOS 宏(define)与常量(const)的正确使用

比如定义一个常量又不想被修改应该这样:
static NSString * const HSCoder = @"汉斯哈哈哈";
static NSString * const collectionCellIdentifier = @"ShareUICollectionViewCell";

七. 其他

  • 在属性命名中,如果类的全名太长,可以使用一些缩写,但这些缩写必须是大家公认,没有任何歧义的。(比如:nav,bg,btn,lb,tf等)。
  • 在函数命名中,推荐使用一些经典的操作应该使用约定的动词,如initWith,insert,remove,replace,add等等。
  • 对于类的method: 左括号另起一行写(遵循苹果官方文档)。这一要求可以使用,但不强制使用,具体可以根据团队开发要求来限定,因为比如我们创建一个UIViewController,里面的方法均没有执行这一要求,所以我们也不强制执行。

作者:ivylee_mr
链接:https://www.jianshu.com/p/c12d9b144b72
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容