IOS开发规范
公司新项目马上要启动,整理一篇规范,供参考。
命名规范
驼峰法,除第一个单词之外,其他单词首字母大写。
属性命名
描述性的单词+变量类型,一目了然,如:
@property(nonatomic,weak)IBOutlet UILabel *titleLabel;
@property(nonatomic,weak)IBOutlet UILabel *dateLabel;
类命名
普通功能也面类命名规范,功能模块前缀+类型/模型/管理
,一目了然,如:
MessageTableViewCell.h
MessageTableViewCell.m
MessageTableViewCell.xib
MessageTableViewController.h
MessageTableViewController.m
MessageTableViewController.xib
ProductViewController.h
ProductViewController.m
ProductViewController.xib
ProductItem.h
ProductItem.m
ProductModel.h
ProductModel.m
UserManager.h
UserManager.m
NetworkManager.h
NetworkManager.m
方法命名
一个规范的方法读起来应该像一句完整的话,读过之后便知函数的作用。
执行性的方法应该以动词开头,小写字母开头。
返回性的方法应该以返回的内容开头,但之前不要加get。如:
-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
-(instancetype)arrayWithArray:(NSArray *)array;
-(ProductModel *)productWithCategory:(NSString *)categoryId;
常量命名
对于常量的命名前面加上字母k作为标记. 如:
static const NSTimeInterval kAnimationDuration = 0.3;
定义作为NSDictionary或者Notification等的Key值字符串时加上const关键字, 以防止被修改. 如:
NSString *const UIApplicationDidEnterBackgroundNotification
枚举命名
对于枚举类型, 经常会看到之前的C的定义方式:
typedef enum : {
CameraModeFront,
CameraModeLeft,
CameraModeRight,
} CameraMode;
作为一个iOS开发要以Objective-C的方式来定义:
typedef NS_ENUM (NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
这边需要注意的是: 枚举类型命名要加相关类名前缀并且枚举值命名要加枚举类型前缀.
图片命名
原则:
1)采用单词全拼,或者大家公认无岐义的缩写(比如:nav,bg,btn等)
2)采用“模块_功能”命名法,模块分为公共模块、私有模块。公共模块主要包括统一的背
景、导航条、标签、按钮背景、图标、默认图等等;私有模块主要根据app的业务
功能模块划分,比如用户中心,消息中心等。
公共模块命名示例:
导航条背影图片:bg_nav_bar@2x.png
导航返回按钮正常:nav_back_normal@2x.png
导航返回按钮选中:nav_back_selected@2x.png
标签item背景正常:tabbar_record_normal@2x.png
标签item背景选中:bg_tabbar_record_selected@2x.png
私有模块命名示例:
首页搜索背景图:home_search@2x.png
首页消息默认背景图:home_info_normal@2x.png
首页消息高亮背景图:home_info_highlight@2x.png
注释规范
属性注释
使用/** 注释 */
的方式,这种方式在引用时Xcode会给出友好提示。
@interface UserItem : BaseModel
/** ID */
@property(nonatomic,assign) NSInteger itemId;
/** 用户名 */
@property(nonatomic,strong) NSString *name;
/** 密码 */
@property(nonatomic,strong) NSString *password;
/** 手机号 */
@property(nonatomic,strong) NSString *phoneNum;
/** 头像 */
@property(nonatomic,strong) NSString *headerPic;
/** 关注人ID */
@property(nonatomic,assign) NSInteger attentionId;
/** 热度 */
@property(nonatomic,assign) NSInteger hotScore;
/** 推荐状态 */
@property(nonatomic,assign) NSInteger commendState;
@end
方法注释
严格采用苹果官方提供的注释标准,这种方式在引用时Xcode会给出友好提示。
/**
对AF进行简单封装
*/
@interface SSNetworkingManager : AFHTTPSessionManager
/**
单利方法
@return 实例
*/
+(instancetype _Nonnull )shareManager;
/**
* 封装的GET请求
*
* @param URLString 请求的链接
* @param parameters 请求的参数
* @param success 请求成功回调
* @param failure 请求失败回调
*/
- (void)SSGET:(NSString *)URLString parameters:(NSDictionary *)parameters success:(Success)success failure:(Failure)failure;
/**
* 封装的POST请求
*
* @param URLString 请求的链接
* @param parameters 请求的参数
* @param success 请求成功回调
* @param failure 请求失败回调
*/
- (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters success:(Success)success failure:(Failure)failure;
/**
* 封装POST图片上传(多张图片) // 可扩展成多个别的数据上传如:mp3等
*
* @param URLString 请求的链接
* @param parameters 请求的参数
* @param picArray 存放图片模型(HDPicModle)的数组
* @param progress 进度的回调
* @param success 发送成功的回调
* @param failure 发送失败的回调
*/
- (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPicArray:(NSArray *)picArray progress:(Progress)progress success:(Success)success failure:(Failure)failure;
/**
* 封装POST图片上传(单张图片) // 可扩展成单个别的数据上传如:mp3等
*
* @param URLString 请求的链接
* @param parameters 请求的参数
* @param picModle 上传的图片模型
* @param progress 进度的回调
* @param success 发送成功的回调
* @param failure 发送失败的回调
*/
- (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPic:(SSImageModel *)picModle progress:(Progress)progress success:(Success)success failure:(Failure)failure;
/**
* 封装POST上传url资源
*
* @param URLString 请求的链接
* @param parameters 请求的参数
* @param picModle 上传的图片模型(资源的url地址)
* @param progress 进度的回调
* @param success 发送成功的回调
* @param failure 发送失败的回调
*/
- (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPicUrl:(SSImageModel *)picModle progress:(Progress)progress success:(Success)success failure:(Failure)failure;
/**
* 下载
*
* @param URLString 请求的链接
* @param progress 进度的回调
* @param destination 返回URL的回调
* @param downLoadSuccess 发送成功的回调
* @param failure 发送失败的回调
*/
- (NSURLSessionDownloadTask *)SSdownLoadWithURL:(NSString *)URLString progress:(Progress)progress destination:(Destination)destination downLoadSuccess:(DownLoadSuccess)downLoadSuccess failure:(Failure)failure;
@end
#pragma mark
视图方法中必须添加mark标记,方便查找文件中的具体方法和理解整个类的结构。
#pragma mark - Lifecycle
-(id)init{}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
#pragma mark - Lazy
- (void)setUpTableView{}
#pragma mark - IBAction
- (IBAction)submitData:(id)sender {}
#pragma mark - Common
- (void)publicMethod {}
- (void)privateMethod {}
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
编码规范
判断nil或者YES/NO
Preferred:
if (someObject) { ... }
if (!someObject) { ... }
Not preferred:
if (someObject == YES) { ...}
if (someObject != nil) { ...}
if (someObject == YES)容易误写成赋值语句, 自己给自己挖坑了...而且if (someObject)写法很简洁.
条件赋值
Preferred:
result = object ? : [self createObject];
Not preferred:
result = object ? object : [self createObject];
如果是存在就赋值本身, 那就可以这样简写.
初始化方法
Preferred:
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;
使用字面量,保证代码更加简洁。
定义属性
Preferred:
@property(nonatomic,assign) NSInteger itemId;
@property(nonatomic,strong) NSString *name;
BOOL赋值
Preferred:
BOOL isAdult = age > 18;
Not preferred:
BOOL isAdult;
if (age > 18)
{
isAdult = YES;
}
else
{
isAdult = NO;
}
拒绝写死值
Preferred:
if (car == Car.Nissan) ...
const int adultAge = 18;
if (age > adultAge) {
...
}
Not preferred:
if (carName == "Nissan") ...
if (age > 18) {
...
}
死值每次修改的时候容易被遗忘, 地方多了找起来就悲剧了。而且定义成枚举或者static可以让错误发生在编译阶段。
复杂的条件判断
Preferred:
if ([self canDeleteJob:job]) { ... }
- (BOOL)canDeleteJob:(Job *)job {
BOOL invalidJobState = job.JobState == JobState.New
|| job.JobState == JobState.Submitted
|| job.JobState == JobState.Expired;
BOOL invalidJob = job.JobTitle && job.JobTitle.length;
return invalidJobState || invalidJob;
}
Not preferred:
if (job.JobState == JobState.New
|| job.JobState == JobState.Submitted
|| job.JobState == JobState.Expired
|| (job.JobTitle && job.JobTitle.length)) {
...
}
专门的方法做专门的事情。
嵌套判断
Preferred:
if (!user.UserName) return NO;
if (!user.Password) return NO;
if (!user.Email) return NO;
return YES;
Not preferred:
BOOL isValid = NO;
if (user.UserName) {
if (user.Password) {
if (user.Email) isValid = YES;
}
}
return isValid;
黄金路径
参数过多
Preferred:
- (void)registerUser(User *user) {
...
}
Not preferred:
- (void)registerUserName:(NSString *)userName
password:(NSString *)password
email:(NSString *)email {
...
}
当发现实现某一功能需要传递的参数太多时, 就预示着你应该聚合成一个model类了...这样代码更整洁, 也不容易因为参数太多导致出错。
回调方法
Preferred:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
函数调用的可知性, 回调时被调用者要知道其调用者, 方便信息的传递, 所以建议在回调方法中第一个参数中加上调用者
本文参考:
//www.greatytc.com/p/da8a471219d1
//www.greatytc.com/p/414bb5a53139