我的iOS Coding Style

前言

  需求是暂时的,变化才是永恒的,面向变化编程,而不是面向需求编程。

  简洁的代码让bug无处藏身,要写出明显没有bug的代码,而不是没有明显bug的代码。

  不要过分追求技巧,降低程序的可读性。

  先把眼前的问题掉,解决好,再考虑将来的扩展问题。

  作为一名合格的程序员,应该要明确一点:我们写的代码不只是给自己看的,优雅的编码风格以及良好的代码注释对我们日常的开发是十分必要的。当我们在编写代码时,要有一个意识:此刻有千千万万人正在看着自己写代码,如何让他们都能迅速看得懂自己写的代码,这就需要我们在平常开发的时候,时时刻刻都要进行代码规范。

一、命名

  命名应该做到含义清楚、使用全称、除众所周知的缩写外不使用缩写,遵循驼峰命名法。

类名

  类名使用大驼峰式命名:每个单词首字母都采用大写字母,带项目缩写前缀。例如:SHBaseViewController

  ViewController的结尾必须以ViewController结束。例如:SHCourseDetailViewController

  View的结尾必须以View结束。例如SHCourseDetailBottomView

  Model的结尾必须以Model结束。例如SHHomeworkModel

  TableViewCell的结尾以Cell结束,并要将所属模块一起表述清楚。例如:SHCourseDetailTeacherCell

  TableView的HeaderView和FooterView以Header和Footer结束,并将所属模块一起表述清楚。例如SHCourseDetailTeacherHeader

属性名

  属性名使用小驼峰式命名:第一个单词首字母小写,后面的单词首字母都以大写开始。例如:

  属性要在property之后空一格;属性的每个关键字之间空一格;括号外面,先空一格再写声明属性;

  属性关键字推荐按照内存管理、原子性、读写、setter、getter的顺序排列。关键字为assign时可以不写。

  Block、NSString、NSNumber、NSArray、NSDictionary、NSSet都需要使用Copy关键字,但是NSMutableString、NSMutableArray、NSMutableDictionary、
NSMutableSet都不得使用Copy关键字。

  NSArray、NSMutableArray、NSSet、NSMutableSet中的元素如果是相同类型,使用__kindof修饰。

  例如:

@property (strong, nonatomic) SHBaseView *backgroundView;
@property (copy, nonatomic) NSString *teacherName;
@property (copy, nonatomic) NSArray<__kindof SHTeacherModel> *teacherModelArray;

常量名

  对于仅限于当前文件的常量,以字符k开头,以static const做修饰。
例如:static NSString *const kIdentifyTeacher = @"teacher";

  对于外部可见的常量,则以当前类的类名开头,在实现文件中定义其值,在头文件中进行extern声明。

宏定义

  使用#define进行宏定义时,所有字母大写,中间以_分割。宏定义中的表达式和变量必须以小括号括起来。

  尽量不要使用宏定义字符串,而应该使用常量来定义。

枚举

  枚举类型的命名与类命名一致,都使用带项目前缀的大驼峰命名法。枚举中的枚举项以该枚举类型名称开头。

  使用NS_ENUM定义通用枚举,使用NS_OPTIONS定义位移枚举。

  例如:

typedef NS_ENUM(NSInteger, SHHomeworkItemType) {
    SHHomeworkItemTypeImage = 1,
    SHHomeworkItemTypeAudio = 2,
    SHHomeworkItemTypeText = 3
};

方法

  方法名采用小驼峰式命名;不能使用new、alloc作为起始单词;不能使用前缀。

  不能使用and连接属性参数;如果方法描述两种独立行为,使用and连接。例如:

- (instancetype)initWithCourseId:(NSString *)courseId courseType:(NSString *)courseType;

  表示对象行为的方法、执行性方法应该以动词开头,但不能以do或does开头,因为这些词毫无意义;也不能在动词前使用副词或形容词修饰;尽量不要使用other、old等泛指性单词。例如:

- (void)insertObject:(ObjectType)anObject atIndex:(NSUInteger)index;

  有返回值的方法应该以返回的内容开头,但不能以get开头。例如:

- (ObjectType)objectAtIndex:(NSUInteger)index;

  Init方法以最少参数为原则,其他init方法在此方法上扩展。

类别(Category)

  类别命名需要带前缀,遵循大驼峰命名法。例如:

UIButton+SHEdgeInsets

协议

  协议名使用Delegate做后缀。必须实现的协议方法用required修饰;可选实现的方法用optional修饰。
  协议方法名使用did和will通知delegate已经发生和将要发生的变化。
  协议方法中的第一个参数建议为当前对象。当只有当前对象一个参数时,方法名要符合实际含义;当协议方法存在两个以上参数的时候,以类名开头,表示此方法属于哪个类。例如:

@protocol SHCourseDetailBottomViewDelegate <NSObject>

- (void)askButtonActionInCourseBottomView:(SHCourseDetailBottomView *)bottomView;

- (void) courseBottomView:(SHCourseDetailBottomView *)bottomView didPressedButtonAtIndex:(NSInteger)index;

@end

  协议的内存管理关键字要使用weak。

二、注释

  优秀的代码大部分是可以自描述的,我们完全可以用代码本身来表达它到底在做什么,而不需要注释的辅助。但以下几种情况比较适合写注释:

  • 公共接口,注释告诉使用接口的人当前类的作用及实现功能;
  • 涉及专业层次的代码,注释表示出实现原理和思想;
  • 容易产生歧义的代码,这种代码最好还是不要存在

  对于注释的内容,相对于“做了什么”,更应该说明“为什么这么做”。

import注释

  当import的文件较多时,需要对这些语句进行分组,并标记每组的类型。例如:

#import "SHHomeCourseDetailViewController.h"
#import <EventKit/EventKit.h>
//view controller
#import "SHTagIntroViewController.h"
#import "SHRecommendViewController.h"
//section
#import "SHCourseDetailLectureSection.h"
#import "SHCourseDetailSubClazzSection.h"
#import "SHCourseDetailUnitCourseSection.h"
#import "SHCourseDetailActivitySection.h"
//cell
#import "SHCourseDetailCommonInfoCell.h"
#import "SHCourseDetailSubClazzCell.h"
#import "SHCourseDetailTagCell.h"
#import "SHCourseDetailUnitCourseCell.h"
#import "SHCourseDetailPracticeCell.h"
#import "SHHomeDetailLiveListCell.h"
#import "SHCourseDetailImageCell.h"
#import "SHHomeCourseWebCell.h"
#import "SHCourseDetailRewardCell.h"
#import "SHCourseDetailActivityPaidCell.h"
#import "SHCourseDetailActivityUnpaidCell.h"
#import "SHCourseDetailActivityEmptyCell.h"
#import "SHCourseDetailActivityIntroCell.h"
//view
#import "SHCourseDetailNavigationView.h"
#import "SHCourseDetailCountDownView.h"
#import "SHCourseDetailBottomView.h"
#import "SHPlayerCoverView.h"
//manager && Service
#import "SHHomeService.h"
#import "SHPayService.h"
#import "SHNewDownloadManager.h"
#import "SHDownLoadManager.h"

属性注释

  较短的注释写在属性之后,用空格隔开;较长的注释写在属性上面。内容特别多的注释使用/* */。例如:

@property (strong, nonatomic) UIView *containerView; //this is a shor comment
//this is a long comment
@property (strong, nonatomic) SHExcellentShareCardView *cardView;

方法注释

  公开或重要的方法、分类、协议都需要做注释。注释使用Xcode自带的快捷键(command+option+/)添加注释。

todo

  未完成或需要后面修改的代码使用//TODO:来注释。例如:

//TODO:YangJian request authority

三、代码格式化

空格

  使用4空格缩进,禁止使用tab字符。设置方法:command+逗号 > Text Editing > Identation。

  指针*与类型之间有一个空格,与变量之间无空格。例如:NSString *teacherName;

  一元运算符与变量之间没有空格;而任何二元、三元运算符左右两边都有一个空格。

  方法声明的-和+之后有一个空格;参数的类型和变量之间无空格;如果参数为对象,参数的类名和*之间有一个空格。例如:

- (void)askButtonActionInCourseBottomView:(SHCourseDetailBottomView *)bottomView;

  左小括号和变量之间不得出现空格;同理右小括号和变量之间也不得出现空

  if、for、while、switch、do等保留字与括号之间必须加空格。

换行与空行

  方法与方法之间空且只空一行。

  在方法开始时的左大括号必须独占一行;代码块中的左大括号建议换行;任何右大括号必须独占一行。

  return语句之前建议加一个空行。

  不要乱加空行,例如在右大括号之前就不要加空行了。

  每行代码一般不超过80个字符,最多不超过100个。可以在Xcode中设置,command+逗号 > Text Editing > Page guide at column设置为100。

四、编码规范

  所有代码块都应使用大括号包括起来,就算只有一行代码也要加上大括号。

if语句

  if语句应尽量穷举所有情况,且每种情况都有明确处理。

  尽量少嵌套,善于使用return提前返回错误,正确情况在最后处理。

  推荐条件判断应该常量在左,变量在右。

  条件表达式过长应单独抽出来,赋值给一个BOOL值。

  不要在条件判断中执行复杂语句,将复杂逻辑判断赋值给一个BOOL值可提高代码阅读性。

switch语句

  每个分支都要用大括号包起来,大括号要将break关键字一起括起来。

  枚举类型不能有default值,除枚举类型外都必须有default分支。

循环语句

  循环体中的语句要考虑性能问题,能移到循环体外的就要移到循环体外。

五、结构

项目结构

  在遵循MVC架构的基础上扩展一些模块。
//TODO:因为项目调整中,此模块后续添加

代码结构

  私有属性使用扩展声明。

  属性都使用懒加载实现getter方法。

  开放只读关键字的属性,在扩展中使用readwrite声明,在头文件中使用readonly声明。

  头文件中少引用其他头文件,引用文件放到实现文件中,在头文件中使用到的类使用@class声明。

  方法的顺序应按照以下顺序,类方法 > dealloc > init > 生命周期 > private > public > action > 代理 > getter;且每个模块之间使用#pragma mark分组。

  尽量轻量级的视图控制器,ViewController只做view的内容更新和屏幕的交互等操作,较大的业务逻辑移到ViewModel中。

  复杂的视图控制器使用子视图控制器。
  类声明文件中在import之后添加NS_ASSUME_NONNULL_BEGIN,在@end之后添加NS_ASSUME_NONNULL_END;方法的返回值和参数如果允许为空,添加nullable修饰。

  适当添加编译标识符。

  过期的代码和文件及时清理。

  不再维护或者将删除的代码使用DEPRECATED_MSG_ATTRIBUTE标识。

AppDelegate

  只添加application相关方法,其他逻辑按功能进行分类。

六、其他

  类应该单一、封闭,少使用单例。初始化的init方法只添加必要属性,非必要参数开放属性。

  TableView使用重用机制,注册重用的方法是:

- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier;

  TableView的高度要做缓存。

  不要对UITalbleView进行封装,事实证明自己封装UITableView就是一个大坑,新人来了以后很不适应。

  一个方法的代码建议不超过100行。

  属性在init、dealloc、setter、getter中使用下划线访问,其他地方使用self.访问。

  block中要记得使用__weak和__strong打断循环引用。

  NSTimer是会引起循环引用的,改用我们自己的BJTimer。

  不要放太多文件到预编译头文件pch中,会使编译所读变慢。

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

推荐阅读更多精彩内容

  • 又是一年春来时,春天是美好的代名词,是一个童话般的意象,春花烂漫,春草青青。闭上眼,想象一下春天是什么样子的,是白...
    东山月明阅读 570评论 2 5
  • 第五十一回 曹仁大战东吴兵 孔明一气周公瑾 要杀关羽这是刘备绝对不会同意的事情,再说之前诸葛已经都说清了,要是突...
    JohnVeeCaptain阅读 313评论 0 2
  • 满庭芳 幸福 咏草吟花,敲平弄仄,万般乐趣其中。餐时难忘,梦有美诗从。庭外潇潇雨歇,心若素、思索凝瞳。伏天热,...
    老财神阅读 163评论 0 4
  • 2015年女教师的一封辞职信——世界那么大,我想去看看,意外走红网络圈。网友赞誉的,评判的都有,并被誉为“世上最具...
    淼淼左阅读 548评论 0 2