版本:1.0
时间:2018年9月20日
1.命名规范
1.1. 属性、数据类型命名规范
1.1.1. 声明的属性和实例变量
控件类型 |
前缀 |
demo |
UIView |
v__ |
vHome |
UILabel |
lbl__ |
lblName |
UIButton |
btn__ |
btnHead |
UITextField |
txf__ |
txfName |
UITextView |
txv__ |
txvSuggest |
UIImage |
img__ |
imgHead |
UIImageView |
imgv__ |
imgvHead |
UIScrollView |
scv__ |
scvHome |
UITableView |
tv__ |
tvHome |
UITableViewCell |
__Cell |
orderCell |
UICollectionView |
cv__ |
cvHome |
UICollectionViewCell |
__Cell |
orderCell |
UICollectionReusableView |
crv__ |
crvHeader |
UISlider |
__Slider |
nightShiftSlider |
UISwitch |
__Switch |
nightShiftSwitch |
UIActivityIndicatorView |
aiv__ |
aivNet |
UISegmentedControl |
__Sc |
optionsSc |
UIProgressView |
pv__ |
pvWebContent |
UIPageControl |
pc__ |
pcBanner |
UIViewController |
vc__ |
vcHome |
UITableViewController |
tvc__ |
tvcHome |
UICollectionViewController |
cvc__ |
cvcHome |
UITabBarController |
tbc__ |
tbcMain |
UIDatePicker |
__DatePicker |
receiveDatePicker |
UIPickerView |
__PickerView |
areaPickerView |
UIebView/WKWebView |
wv__ |
wvMain |
1.1.2 BOOL类型属性命名
- 需要指定getter方法、属性名中不要带is、has、had、have,例如:
@property (assign, getter=isEditable) BOOL editable;
1.1.3 常量命名
- 不要使用魔法数字,就是1.2.3.4...。如果是一组有相近意义的数字,那么定义为枚举,如果只有单个或没有相近意义,那么定义为常量数字。
代码 |
评价 |
if errorCode == 10096 ... |
后续维护人员怎么可能知道10096是什么含义?改动起来也很麻烦 |
static NSInteger const kOverTimeErrorCode = 10096; if errorCode == kOverTimeErrorCode; |
很好,kOverTimeErrorCode 常量有自身的意义,又代表了实际值10096 |
。 |
- 使用const修饰常量,如果只在一个文件中使用,那么开头使用static修饰。例:
static NSInteger const kOverTimeErrorCode = 10096;
- 不要使用宏定义常量
- 定义宏的时候前缀和后缀不要使用双下划线,如:MACH,因为编译器定义的宏都是以双下划线作为开头和结尾的。
- 定义给外部使用的常量,在.h文件中使用 UIKIT_EXTERN 或 FOUNDATION_EXPORT 修饰。例:
// .h
UIKIT_EXTERN NSString *const UITableViewIndexSearch;
// .m
NSString *const UITableViewIndexSearch = @"_UITableViewIndexSearch";
1.1.4 通知常量的命名
- 通知常量的命名规则,[Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification
代码 |
NSApplicationDidBecomeActiveNotification |
NSWindowDidMiniaturizeNotification |
NSTextViewDidChangeSelectionNotification |
NSColorPanelColorDidChangeNotification |
1.1.5异常常量的命名
- 异常常量的命名规则:[Prefix] + [UniquePartOfName] + Exception
代码 |
NSColorListIOException |
NSColorListNotEditableException |
NSDraggingException |
NSFontUnavailableException |
1.2代码命名规范基础
1.2.1 一般原则
1.2.1.1 清晰性:
- 方法清晰又简洁那是最好不过了,但是不应该为了简洁性而降低了清晰性,清晰性才是第一☝️。例:
代码 |
评价 |
insertObject:atIndex: |
很好 |
insert:at: |
不清晰,insert 什么东西? at了什么? |
removeObjectAtIndex: |
很好 |
removeObject: |
很好 |
remove: |
不清晰,移除了什么呢? |
代码 |
评价 |
destinationSelection |
很好 |
destSel |
不够清晰,不知道做什么 |
setBackgroundColor: |
很好 |
setBkgdColor: |
不清晰 |
- 也许你觉得你的缩写是很普遍的,大家都知道的,然而并不是。因为大家的英语水平是参差不齐的。
- 但是有些缩写是官方的,很普及,如:HTML、PPT,这些可以放心大胆的使用
- 避免API名称中的歧义
代码 |
评价 |
sendPort |
这是代表“发送到端口”(动词),还是代表“发送端口”(名词) |
displayName |
是“显示名字”(动词),还是“需要显示的名字”(名词) |
1.2.1.2 一致性
- 和cocoa 的编码规范保持一致性,如果你在命名的时候不确定,可以先去翻翻cocoa的头文件作为参考
- 当一个方法使用多态时,一致性非常重要。在不同类(继承体系)中,做相同事情的方法应该有相同的名字(这也是多态的必要条件)
1.2.1.3 命名中不要重复描述
代码 |
评价 |
NSString |
很好 |
NSStringObject |
重复描述了,不好 |
代码 |
评价 |
NSUnderlineByWordMask |
很好 |
UIApplicationWillEnterForegroundNotification |
很好 |
1.2.2 前缀
- 通用性极高的控件,使用项目名开头,如(AL,JCY)
1.2.3 方法首字母规定
- 方法名首字母小写,特殊名称除外,如:HTML、PDF 等
- 每个参数的首字母小写:
代码 |
评价 |
fileExistsAtPath:isDirectory: |
很好 |
FileExistsAtPath:FsDirectory: |
不好,跟苹果的规范不一致 |
- 首字母不要使用_开头,因为不知道哪一天苹果爸爸的私有方法就被你给覆盖了
1.2.4类和协议名
- 类名必须代表该类含义的名称
- 如果一个协议和任何类都没有联系的话,这个类可以用...ing结尾,与类作区分,如NSCoding, NSCopying等
代码 |
评价 |
NSLocking |
很好,看起来就知道是个协议 |
NSLock |
不好,看起来感觉就是一个类 |
- 如果一个协议与某个类相关联,那么这个协议就以【类名+协议名】作为整体协议名,如:UITableViewDelegate
1.2.5 头文件
- 如果一个协议和任何类都没有联系的话,将这个协议单独作为一个文件
- 如果有几个类、协议相互关联的话,可以放入头一个头文件中
代码 |
评价 |
NSString.h |
NSString和NSMutableString都在里面 |
NSLock.h |
NSLocking协议、NSLock、NSConditionLock、NSRecursiveLock都在里面 |
- 如果是一个框架、那么都需要有一个头问件,以框架命名,包括框架所有的公共头文件,如:UIKit.h
- 如果是一组相关的常量、函数、结构体、枚举等其他数据类型,可以放入一个公共的头文件中
1.3方法命名
1.3.1 通用规则
- 方法名首字母小写(特殊名称除外:如HTML,PDF 等)
- 每个参数的首字母小写
- 如果方法代表对象要做的事情,那么以动词作为方法开头。但是不要使用do或者does作为开头,因为没有意义,当然也没有必要给动词新增形容词,比如:【使劲去解析】。。。
- 如果方法是返回一个属性,那么方法名可以直接使用该属性相关的名词,不要在方法开头添加“get”等动词。
代码 |
评价 |
- (NSSize)cellSize; |
很好 |
- (NSSize)calcCellSize; |
calculate没有必要 |
- (NSSize)getCellSize; |
get没有必要 |
代码 |
评价 |
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag; |
很好 |
- (void)sendAction:(SEL)aSelector :(id)anObject : (BOOL)flag; |
第二个和第三个参数都没有关键词,看不懂 |
- 参数前的关键词是要经过描述的关键词,而不是不相关的关键词
代码 |
评价 |
- (id)viewWithTag: (NSInteger)aTag; |
很好,WithTag明确描述了这个参数 |
- (id)taggedView:(int)aTag; |
不好,:aTag之前没有描述这个参数,而是taggedView,这与aTag是不符的 |
- 新增一个比原方法更多参数的方法时,将新增的参数排列在原方法的参数后面
代码 |
评价 |
- (instancetype)initWithFrame:(CGRect)frameRect; |
原方法 |
- (instancetype)initWithFrame:(CGRect)frameRect name: (NSString *)name |
新增了一个参数,紧跟在后面,很好 |
代码 |
评价 |
- (int)runModalForDirectory:(NSString *)path file:(NSString *) name types: (NSArray *)fileTypes; |
很好 |
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes; |
and 没有必要 |
- 如果一个方法用来描述两个独立的操作,使用“and”链接
代码 |
评价 |
- (BOOL)openFile:(NSString *)fullPath withApplication: (NSString *)appName andDeactivate:(BOOL)flag; |
这个and用来代表连个独立的操作,可以使用 |
1.3.2访问方法
- BOOL值的属性不要使用is、has、had、have开头,指定getter方法为is、has、had、have开头
- 只有对需要返回多个参数的方法时,才使用get。(多个参数,使用指针作为返回)
代码|评价|
- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;|多个返回参数使用get
1.3.3代理方法
代码 |
评价 |
- (BOOL)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath |
以tableView开头 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
以application开头 |
代码 |
评价 |
- (void)applicationWillResignActive:(UIApplication *)application |
以application开头,参数拼接到最后 |
- 在代理方法中通过添加will、did来修饰事件发生的时机
1.3.4方法参数
- 在方法中不要包含poiner 或 ptr
- 避免使用1个字母或者两个字母参数
- 不要使用缩写作为参数
1.3.5私有方法
- 不要使用下划线作为私有方法的前缀
- 如果一定要添加前缀,可以使用【项目名字母缩写_】作为前缀
1.4函数命名
1.4.1 当一个方法中涉及的对象始终时单例对象,或者不涉及任何对象时,请使用函数,不要使用类方法/对象方法。
1.4.2函数命名规则
- 函数用类和常量相同的类型开头
- 一般函数名称中包含描述描述函数的作用动词:
代码 |
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height) |
NSDecimalCompact(NSDecimal *number) |
代码 |
unsigned int NSEventMaskFromType(NSEventType type) |
float NSHeight(NSRect aRect) |
const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)
2.通用缩写
2.1苹果中常用的缩写
缩写 |
全写 |
alloc |
Allocate |
alt |
Alternate |
app |
Application |
calc |
Calculate |
dealloc |
Deallocate |
func |
Function |
horiz |
Horizontal |
info |
Information |
init |
Initialize |
int |
Integer |
max |
Maximum |
min |
Minimum |
msg |
Message |
nib |
Interface Builder archive. |
pboard |
Pasteboard |
rect |
Rectangle |
Rep |
Representation |
temp |
Temporary |
vert |
Vertical |
2.2 一些比较有名气的缩写
缩写 |
ASCII |
PDF |
XML |
HTML |
URL |
RTF |
TIFF |
HTTP |
JPG |
PNG |
GIF |
LZW |
ROM |
RGB |
CMYK |
MIDI |
FTP |
3.开发框架的一些技巧和规范
3.1 initialization类方法
- 这个方法里一般可以设置类的版本号
- 运行时会想类的继承链上的所有类发送initialize消息,所以肯能导致一个类的initialize方法被调用多次(因为子类没有实现,只能往上查找)
- 可以使用dispatch_once 来只执行一次,也可以使用if (self == [NSFoo class]) {...}来执行指定逻辑
- 不要显示调用initialize方法,如果你需要第一次触发一个类的initialize方法,你可以这样[UIImage self] 。
3.2版本和兼容性
*当为你的类新增了一些类或者方法,通常没有必要为每个类指定版本号。可以使用 respondsToSelector: 来兼容新老版本。
4.文件规范
4.1 .h文件
- 类的.h文件不要暴露不必要属性与实例变量
- 类的.h文件在引用的时候,非必要的文件使用@class声明类,不要使用import
- 协议如果是需要给外部使用者知晓的,如NSCoping,则在.h文件中声明,否则只在.m中文件中声明
- .h中,方法的参数、返回值如果是对象,则在参数和返回值里加入nullable / nonnull修饰符,指明返回值/参数是否可能为空
- 公开的属性,如果外界不能更改,请使用readonly修饰,在.m的扩展。中再使用readWrite重新声明(readWrite可以省略)
- .h中方法参数个数超过三个,或者方法过长影响阅读时,每个参数换行显示,以:(冒号)对齐。
- 公开方法如果不是一眼能看明白,那么要添加注释,快捷键:command + option + /
- 注释中写明特殊情况,如:如果发生错误,那么error = kNetWrong
- .h中对公开的常量进行声明
4.2 .m文件
- 文件行数尽量控制在500行内,否则考虑重构
- 方法分类
方法分类 |
#pragma mark - class methods |
#pragma mark - life cycle methods |
#pragma mark - public methods |
#pragma mark - event methods |
#pragma mark - update and animation UI methods |
#pragma mark - sdk Delegate |
#pragma mark - customDelegate method(如:#pragma mark - UITableViewDelegate method,这样cmd+左键点击UITableViewDelegate就能进入这个协议所在的文件,很方便查看) |
#pragma mark - private method(私有方法) |
#pragma mark - messageHandle (观察者处理) |
#pragma mark - getters and setter method |
- .m中对所有的#import"头文件"进行分类处理
#import |
//系统头文件 |
// ViewController |
// View |
// ViewModel |
// Model |
// API |
// Manager |
// Category |
-
Setter / getter方法尽量写在.m 文件的最下面,因为你每次滚动文件的时候肯定不想看到他们
- 两个方法之间空一行(注释为开头行)
- 方法中的switch (enumType) 不要加default:分支,因为未来在这个enumType加了一种类型的时候,编译器会在这个switch的地方警告提示
-
一个方法的行数尽量不要超过一个屏幕的高度。大约40~50行。
- 扩展中定义的属性,相同类的尽量写在一起。如UI类的属性放在一起,data类的放在一起
- 一个方法只做一件事
- 一个方法尽量能够不依赖全局变量或属性做事情(函数式比编程思想,具体可以去了解一下)
- 方法中的特殊业务/边界判断,请注释
5.其他
- 若if/while 等判断里的条件比较多或者比较长的时候,在逻辑运算符之前换行
if (job.JobState == JobState.New
|| job.JobState == JobState.Submitted
|| job.JobState == JobState.Expired
|| (job.JobTitle && job.JobTitle.length)) {
...
}
if (!user.userName) return NO;
if (!user.password) return NO;
if (!user.email) return NO;
return YES;
// 这个写法不是很好
if (!isNotMember) {...} else {...}
// 这个写法很清晰
if (isNotMember) {...} else {...}
- 声明一个OC对象使用
变量类型 *变量名
,而不是变量类型* 变量名
,也不是变量类型*变量名
//这样是规范的
NSString *name
//以下都是不规范的
NSString * name
NSString* name
NSString*name
- 可以使用字面量语法初始化的类,用可读性高的字面量进行初始化
- 声明枚举,用NS_ENUM宏进行声明
typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
RWTLeftMenuTopItemTypeMain,
RWTLeftMenuTopItemTypeShows,
RWTLeftMenuTopItemTypeSchedule
};
!bValue
~iValue
++iCount
*strSource
&fSum
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
for(int i = 0; i < 10; i++)
5.图片命名规范
- 工程中的图片一律放入Assets.xcassets文件夹中进行管理
- 工程中的文件夹以模块为界进行创建,如果一个模块中还有子模块,那么可以再在其中对应文件夹以区分子模块。
- 工程中的图片命名规则:能够描述清楚图片的用途和用在什么地方 例:
- Home(工程的模块文件夹)
- home_city
- home_scan
- QXC(子模块文件夹)
- qxc_shop_basket_gray
- qxc_shop_basket
6.工程前缀
7.Apple的代码规范
😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄
以上都是个人的总结和建议,如果有什么错误或者不合适的地方,以及需要补充的地方,请大家多多提出自己宝贵的意见和建议。
😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄
网友评论