iOS APP开发规范(Objective-C)

前言

为什么要制定一套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 - 方式对类的方法进行分组,会使代码分区,看起来非常赏心悦目。
如图:


iOS APP开发规范(Objective-C)_第1张图片
E84C574F-EB90-4EB0-BB6F-65F90D32A30B.png

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,里面的方法均没有执行这一要求,所以我们也不强制执行。

如有纰漏,欢迎留言狂喷

没有伤害,就没有进步。


  • QQ 375701847。

你可能感兴趣的:(iOS APP开发规范(Objective-C))