注册

你确定你会写代码---iOS规范补充

Pod update注意

1、先执行pod repo update 公司内部库specs
2、再执行pod update --no-repo-update这样就不会update github_specs,速度快

JSONSerialization

涉及到JSON Object<->NSData数据转换的地方,注意对NSError的处理和JSON Object合法性的校验,如:

BOOL validate = [NSJSONSerialization isValidJSONObject:parament];
if (!validate) {
// 对不是合法的JSON对象错误进行处理
return;
}
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parament options:NSJSONWritingPrettyPrinted error:&error];
if (error) {
// 对数据转换错误进行处理
return;
}

合法JSON对象满足:
1、Top level object is an NSArray or NSDictionary
2、All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
3、All dictionary keys are NSStrings
4、NSNumbers are not NaN or infinity

补充一些代码规范、开发约定

写if else语句时可以else不换行紧跟if的}括号,但写if else if时,为了保持条件{}的可读性,务必请换行书写:

// if else
BOOL flag = YES;
if (flag) {

} else {

}

// if else if
BOOL flag = YES;
BOOL elseIfFlag = (1+1-1+2 == 5);
if (flag) {

}
// 这里换行书写
else if(elseIfFlag) {

}

对于@property声明的属性,如果初始化设置复杂,请采用懒加载getters方式,对于简单初始化的,应在.m文件中提供统一的-initData初始化数据的方法。

/// 懒加载方式-内部配置
@property(nonatomic, strong)UIView *redView;
/// 统一初始化
@property(nonatomic, strong)NSMutableArray *dataSourceArray;

/// 统一数据初始化
- (void)initData{
_dataSourceArray = [NSMutableArray new];
}

/// 懒加载
- (UIView *)redView{
if (!_redView) {
_redView = [UIView new];
_redView.backgroundColor = UIColor.redColor;
}
return _redView;
}

对于NSDictionary、NSArray等的初始化,为提高可读性起见,建议采用语法糖的初始化方式:

_dataSourceArray = [@[@"1", @"2"] mutableCopy];
_parameters = [@{@"action": @"add", @"id": @"22"} mutableCopy];

// X: 不推荐这样做
_dataSourceArray = [NSMutableArray new];
[_dataSourceArray addObject:@"1"];
[_dataSourceArray addObject:@"2"];

_parameters = [NSMutableDictionary new];
[_parameters setValue:@"add" forKey:@"action"];
[_parameters setValue:@"22" forKey:@"id"];

对于Category中的对外公有方法,务必采用categoryName_funcName的命名方式,以区别于主类里没有前缀的方法:

// TALPlayer+LogReport.h

/// 加载播放器
- (void)logReport_loadPlayer;
/// 开始播放
- (void)logReport_startPlay;

对于Category里的私有同名方法,可采用下划线方式如_mainClassFuncName以区别.
对于主类里的私有属性,在多个Category访问时,可采用属性中间件的方式,拆出一个独立的MainClass+InternalProperty来提供一些getters方法:

// TALPlayer+InternalProperty.h

- (TALPlayerLogModel *)internalProperty_logModel;
- (TALPlayerStaticsModel *)internalProperty_staticsModel;


// TALPlayer+InternalProperty.m

- (TALPlayerLogModel *)internalProperty_logModel{
// 这里为方便以后调试断点用,建议拆开2行写
id value = [self valueForKey:@"logModel"];
return value;
}

对于需要跟服务器交互的网络请求参数字符串,务必独立出对应Category的DataInfoKeys扩展文件,方便查询、注释、全局引用、修改和拼写纠错:

// TALPlayer+LogReportDataInfoKeys.h

/// action
extern NSString *const LogReportDataInfoActionKey;
/// 心跳
extern NSString *const LogReportDataInfoActionHeartBeatKey;
/// 严重卡顿
extern NSString *const LogReportDataInfoActionSeriousBufferKey;


// TALPlayer+LogReportDataInfoKeys.m

// action
NSString *const LogReportDataInfoActionKey = @"action";
/// 心跳
NSString *const LogReportDataInfoActionHeartBeatKey = @"heartbeat";
/// 严重卡顿
NSString *const LogReportDataInfoActionSeriousBufferKey = @"seriousbuffer";


// 使用
#import "TALPlayerLogReportDataInfoKeys.h"

NSMutableDictionary *info = [NSMutableDictionary new];
info[LogReportDataInfoActionKey] = LogReportDataInfoActionHeartBeatKey;
// info[XXXKey] = value;

对于.h及.m文件中默认#pragma mark的规范,推荐如下:

// XXX.h

#pragma mark - Protocol

#pragma mark - Properties

#pragma mark - Methods

// XXX.m

#pragma mark - Consts

#pragma mark - UI Components

#pragma mark - Data Properties

#pragma mark - Initial Methods

#pragma mark - Lifecycle Methods

#pragma mark - Override Methods

#pragma mark - Public Methods

#pragma mark - Private Methods

#pragma mark - XXXDelegate

#pragma mark - Getters

#pragma mark - Setters

如上相关#pragma字符在Xcode中的自动配置,有机会我会单独分享给大家。
Xcode FileTemplate路径:Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/Source/Cocoa Touch Class.xctemplate/


对于OC文件中注释规范说明:

//MARK: mark here(类似于#pragma mark,只不过没有横线)

//TODO: todo here

//FIXME: fix me later

//???: What is this shit

//!!!: DO NOT TOUCH MY CODE

说明:
对于单行注释,尽量用//代替/**/格式,,务必请在//后加一个空格,再进行内容补充,如:// 这是单行注释而不要写成//这是单行注释
对于SDK内部私有方法,如果无参数,则采用/// 这是无参数方法注释格式;
对于SDK需要向外暴露的接口方法注释,请务必按照AppleDoc编写,写明@param、@return等:

/**
* 这是一个demo方法
* @param param1 第一个参数
* @param param2 第二个参数
* @return BOOL值
*/
- (BOOL)thisIsADemoFuncWithParam1: (NSString *)param1
param2: (NSInteger)param2{
return NO;
}

1、对于@property申明的SDK公开属性,务必写成/* 这是SDK公开属性注释 */,方便调用时Xcode提示;

2、对于SDK内部使用的属性,最好写成/// 这是属性注释而不是/**/;

3、另外,务必让对于>=2个参数的方法,各个参数折行对齐,务必保持.h和.m方法参数格式一致;

4、对于方法名的统一性说明:

  4.1 如果方法是功能性的,处理某些事件、计算、数据处理等的私有方法,则可定义方法名为handleXXX:,如-handleRedBtnClick:、-handleResponsedData:、-handlePlayerEvent:等;

  4.2 对于一些需要暴露的公有方法,则命名最好按照n的功能命名,如对于一个TALPlayer它可以play、stop、resume等;

  4.3 对于可以switch两种状态切换的状态方法,最好命名为toggleXXX:(BOOL)on,如- (void)toggleMute:(BOOL)on;

5、对于一些状态描述性的属性,可以用needs、is、should、has+adj/vb组合形式,如needsAutoDisplay、shouldAutoRotateOrientation、isFinished、hasData或hasNoData等;

对于一些NS_ENUM枚举定义,务必遵循统一前缀方式:

typedef enum : NSUInteger {
TALPlayerEventA = 0,
TALPlayerEventB,
TALPlayerEventC,
} TALPlayerEvent;
// 或者
typedef NS_ENUM(NSUInteger, MyEnum) {
MyEnumValueA,
MyEnumValueB,
MyEnumValueC,
};

6、对于一些全局宏的定义,务必SDK前缀全大写_NAME_组合如TALPLAYER_GLOBAL_MACRO_NAME,对于const类型的常量,务必加上k前缀,命名为kConstValue;

7、对于一些typedef的Block,命名最好指明Block的类别+用途,如TALPlayerLogReportHandler,如果有功能性区分的话,则可以定义为TALPlayerLogReportCompletionHandler、TALPlayerLogReportSuccessHandler、TALPlayerLogReportFailureHandler注意是名词组合形式;

8、调用Block时,一定要对block对象进行nil值判断,防止崩溃handler ? handler() : nil;

9、所有对于NSString校验的地方,都应该校验其length > 0,而不是!str;

10、所有对于NSURL校验的地方,都应该校验其[URL.scheme.lowercaseString isEqualToString: @"https"]方式,而不是!URL;

链接:https://www.jianshu.com/p/deb117eca9ea

0 个评论

要回复文章请先登录注册