开发是个持续性的过程,无论项目大小,都需要一套严格的开发规范。遵守规范的好处,自然不用多说,我只想就项目开发中的代码文件结构谈谈自己的理解。
先来看看下面这张图吧,这是公司目前的一个项目,框架是我搭建的,在项目启动前期,我将文件分为如下六大类:(注明:YZ是项目的缩写前缀)
1、AppDelegate
放置AppDelegate文件,有时候项目会需要自定义自己的AppDelegate来处理更多的消息通知类的东西。
2、Main
主要放的是项目的每个模块对应的代码。因为本项目是用户端和企业端互相切换身份而共存的,所以Main下面我分为:Company和User,并在相应目录下新增各自的业务功能页面
3、Common
是项目中通用的模块,Model & View & VC的集合。
4、Expand
放置的是宏定义、封装好的网络和工具、分类、常量定义等。其中就Const和Macros文件夹下子目录做介绍:
1)Const:该文件夹下放置了YZConst类, 定义了App相关的常量和通知、userDefault名称
2)Macros:包含YZHeader.h、YZNetUrlConfig.h、YZDefine.h、YZConfig.h四个头文件。前两个分别是添加常用头文件需要#import的类和定义所有的网络请求地址,YZDefine.h和YZConfig.h两个头文件定义的东西,详见如下:
//
// YZDefine.h
// YZUser
//
// Created by shuni on 2017/5/27.
// Copyright © 2017年 shuni. All rights reserved.
// 定义常用方法和常量
#ifndef YZDefine_h
#define YZDefine_h
#define WEAKSELF __weak typeof(self) weakSelf = self;
//测试模式 true,正式上线模式 false
#define DEBUG_MODE true
#if DEBUG_MODE
#define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
/*
* Singleton
*/
//单例对象定义
#define DEFINE_SINGLETON_FOR_HEADER(className) \
\
+ (className *)shared##className;
//单例对象实现
#define DEFINE_SINGLETON_FOR_CLASS(className) \
\
+ (className *)shared##className { \
static className *shared##className = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
shared##className = [[self alloc] init]; \
}); \
return shared##className; \
}
/*
* Standard UserDefaults
*/
#define kStandardUserDefaults [NSUserDefaults standardUserDefaults]
#define kStandardUserDefaultsObject(_KEY) [kStandardUserDefaults objectForKey:_KEY]
#define kSaveStandardUserDefaults(_O,_K) [kStandardUserDefaults setObject:_O forKey:_K]
#define kRemoveStandardUserDefaults(_K) [kStandardUserDefaults removeObjectForKey:_K]
#define kStandardUserDefaultsSync [kStandardUserDefaults synchronize]
/*
* UIColor
*/
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
#define UIColorFromRGBA(rgbValue, _A) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:_A]
#define kColorWithRGB(_R,_G,_B) ((UIColor *)[UIColor colorWithRed:_R/255.0 green:_G/255.0 blue:_B/255.0 alpha:1.0])
#define kColorWithRGBA(_R,_G,_B,_A) ((UIColor *)[UIColor colorWithRed:_R/255.0 green:_G/255.0 blue:_B/255.0 alpha:_A])
/*
* Screen size
*/
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
/*
* App info
*/
#define kAppDisplayName [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]
#define kAppVersion [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
#define kAppIdentifier [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]
#define kAppBuildVersion [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]
#endif /* YZDefine_h */
//
// YZConfig.h
// YZUser
//
// Created by shuni on 2017/5/27.
// Copyright © 2017年 shuni. All rights reserved.
// 定义全局变量、Block和枚举类型
#ifndef YZConfig_h
#define YZConfig_h
/*
* 全局变量定义
*/
//默认字体
static NSInteger NavBarRightTitleFont = 14;
//默认高度
static NSInteger NavPortraitHeight = 64;
static NSInteger NavPortraitStatusHeight = 20;
static NSInteger NavPortraitNoStatusHeight = 44;
static NSInteger NavLandscapeHeight = 32;
static NSInteger TabBarHeight = 49;
//获取验证码倒计时间隔
static int kGetCodeTime = 60;
//录制默认最大最时长
static float kYZMinRecordTime = 6;
static float kYZMaxRecordTime = 10;
//上传的视频限制
static float kYZUploadMaxTime = 60; //上传的视频最长视频
static float kYZUploadMinWidth = 720; //上传的分辨率最低提醒
static float kYZUploadMaxBuff = 200; //上传视频大小限制
//整个水印的高/宽比
static float kYZWatermarkComplateHWScale = 2277.0/1280.0;
/*
* Block定义
*/
typedef void(^YZNetCompletionHandler)(NSURLResponse *response, id responseObject);
typedef void(^YZNetErrorCompletionHandler)(NSURLResponse *response, id responseObject, NSError * error);
typedef void(^YZNetUploadCompetionHandler)(NSURLResponse *response, id responseObject);
typedef void(^YZNetErrorUploadCompetionHandler)(NSURLResponse *response, id responseObject, NSError * error);
typedef void(^YZNetDownloadCompetionHandler)(NSURLResponse *response, NSURL *filePath);
typedef void(^YZNetErrorDownloadCompetionHandler)(NSURLResponse *response, NSURL *filePath, NSError * error);
typedef void(^YZCommonToolVedioCompletionHandler)(NSURL *assetURL, NSError *error, BOOL isVideoAssetvertical);
typedef void(^YZMyHeaderItemSelectedBlock)();
typedef void(^YZPositionCellSelectedBlock)();
typedef void(^YZSendResumeBlock)(UIButton *sendResumeBtn);
typedef void(^YZGotoChatBlock)(UIButton *chatBtn);
typedef void(^YZSignUpBlock)(UIButton *signupBtn);
typedef void(^YZShowLocationInMapBlock)();
typedef void(^YZShowCompanyInfoBlock)();
typedef void(^YZEmptyViewGotoPositionBlock)();
typedef void(^YZVideoChangedBlock)();
typedef void(^YZFinishedCropImagesBlock)(NSArray *images);
typedef void(^YZUnInterviewBtnSelectedBlock)();
typedef void(^YZEndedBtnSelectedBlock)();
typedef void(^YZPositionTypeViewHideBlock)(NSArray *selectedPostionArray);
typedef void(^YZResumeListClickBlock)();
typedef void(^YZPositionDetailPublisherViewCallBlock)();
typedef void(^YZPositionDetailPublisherViewArrowBlock)();
typedef void(^YZNetToolInitConfigFinishBlock)();
typedef void(^YZStartMakeResumeVCPlayVideoBlock)();
typedef void(^YZStartMakeResumeVCStopVideoBlock)();
typedef void(^YZTalentGenderViewSelItemBlock)(NSString *itemName);
typedef void(^YZTalentCityViewSelItemBlock)(NSDictionary *provinceDic, NSDictionary *areaDic);
typedef void(^YZClickChatBtnPopViewBtnClickBlock)();
typedef void(^YZChoosePostVCSelectedItemBlock)(NSString *positionId);
//刷新企业基础信息回调
typedef void(^YZReloadCompanyInfoComplete)();
//职位详情的初始化完成回调
typedef void(^YZResumeDetailVCInitComplete)();
typedef void(^YZCreatePostInitComplete)();
/*
* 枚举类型定义
*/
typedef NS_ENUM(NSInteger, YZBarItemPostion) {
YZBarItemPostionLeft = 0,
YZBarItemPostionRight
};
//网络状态
typedef NS_ENUM(NSInteger, YZNetReachabilityStatus) {
kYZNetReachabilityStatusUnknown = -1,
kYZNetReachabilityStatusNotReachable,
kYZNetReachabilityStatusReachableViaWWAN,
kYZNetReachabilityStatusReachableViaWiFi
};
//网络状态回调Block
typedef void(^YZNetReachabilityStatusComplete)(YZNetReachabilityStatus netStatus);
typedef NS_ENUM(NSUInteger, YZUserInfoType) {
kYZUserInfoUID = 1,
kYZUserInfoUserName,
kYZUserInfoAvatarImg,
kYZUserInfoResumeID,
kYZUserInfoAccessToken,
kYZUserInfoUserPhone,
kYZUserInfoUserType,
kYZUserInfoUserRequestURL,
kYZUserInfoRongCloudToken
};
typedef NS_ENUM(NSUInteger, YZCompanyInfoType) {
kYZCompanyInfoID = 1, //公司ID
kYZCompanyInfoName, //公司名称
kYZCompanyInfoInfo, //公司介绍
kYZCompanyInfoEmail, //公司邮箱
kYZCompanyInfoType, //公司type
kYZCompanyInfoAreaId, //公司区域ID
kYZCompanyInfoProvName, //公司的省
kYZCompanyInfoCityName, //公司市
kYZCompanyInfoAddress, //公司详细地址
kYZCompanyInfoState, //公司审核状态(状态0:审核中,1:正常,2:封号,3未通过)
kYZCompanyInfoJobCount, //公司发布岗位数
kYZCompanyInfoUserAvater,//公司头像
kYZCompanyInfoUserName, //公司注册时填写的用户名
kYZCompanyInfoLinkCount //公司已与用户聊天个数
};
typedef NS_ENUM(NSUInteger, YZCompanyReviewState) {
YZCompanyInReview = 0, //审核中
YZCompanyInNormal, //正常
YZCompanyInBlock, //封号
YZCompanyInFail //未通过
};
typedef NS_ENUM(NSUInteger, YZConfigType) {
YZConfigPostArray = 1, //职位
YZConfigSalary, //薪资
YZConfigDegree, //学历
YZConfigSpecialtyTags, //个人标签和职位诱惑
//公共的配置configBase
YZConfigShareToFriend, //app分享给好友
YZConfigShareToZone, //app分享到朋友圈/QQ空间
YZConfigLoginShare, //第三方登陆和分享是否全部显示,0不开启,1全部显示
YZConfigCurrentVersion, //服务器版本地址
YZConfigUpgradeVersionUrl, //升级的网址
YZConfigShouldForceUpgrade, //强制升级
YZConfigUpgradeDesc, //升级描述
YZConfigRouter, //跳转url
YZConfigBackgroundMusic, //视频背景音乐
YZConfigCompanyLinkLimit, //企业与用户聊的限制
YZConfigUserLookLimit //用户查看职位的限制
};
typedef NS_ENUM(NSUInteger, YZMimeType) {
kYZMimeTypeImgPng = 1, //png格式
kYZMimeTypeImgJpg, //jpg格式
kYZMimeTypeVideoMov, //mov格式
kYZMimeTypeVideoMp4 //mp4格式
};
typedef NS_ENUM(NSUInteger, YZPrivateAuth) {
YZAuthorized = 1, //用户允许
YZDenied, //用户拒绝
YZNotDetermined //用户尚未选择
};
typedef NS_ENUM(NSUInteger, YZLanguage) {
YZLanguageEn = 1, //英文
YZLanguageTC, //繁体中文
YZLanguageCN //简体
};
typedef NS_ENUM(NSUInteger, YZVideoDealType) {
YZVideoAddWater = 1 , //增加水印
YZVideoCrop, //裁剪视频
YZVideoMontage //视频拼接
};
//录像的状态
typedef NS_ENUM(NSUInteger, YZRecordState) {
kYZRecordNone = 1,
kYZRecordStart, //开始录制
kYZRecordPause, //暂停录制
kYZRecordDone //完成录制
};
//时间戳快速转换为时间字符串
typedef NS_ENUM(NSUInteger, YZQuickFormatType) {
kYZQuickFormateTypeNone = 0, //自己定义转换
kYZQuickFormateTypeYMD, //年月日 2010-09-02
kYZQuickFormateTypeMD, //月日 09-02
kYZQuickFormateTypeYMDTime, //年月日时间 2010-09-02 05:23:17
kYZQuickFormateTypeTime, //时间 05:23:17
kYZQuickFormateTypeMDTime //月日时间 09-02 05:23
};
//popup的消失动画
typedef NS_ENUM(NSUInteger, YZPopupviewAnimation) {
kYZPopAnimationNone = 1, //无动画直接消失
kYZPopAnimationPopup, //上划弹出
kYZPopAnimationScale, //缩放直至消失
};
//职位类型
typedef NS_ENUM(NSUInteger, kYZPositionType) {
kYZPositionPartTime, //兼职
kYZPositionFullTime, //全职
kYZPositionAnnouncement //通告
};
//职位发布人类型
typedef NS_ENUM(NSUInteger, kYZPositionPublisherType) {
kYZPersonalPublisher, //个人
kYZEnterprisePublisher //企业
};
//录制的方案
typedef NS_ENUM(NSUInteger, YZRecordType) {
kYZRecordVedio = 1, //录制
kYZChangeVedio //重录
};
//图片裁剪类型
typedef NS_ENUM(NSUInteger, PhotoClipType) {
PhotoClipTypeCircle = 0,
PhotoClipTypeSquare
};
//已投递的职位状态
typedef NS_ENUM(NSUInteger, YZPostedPositionStatusType) {
kYZUninterviewPosition, //待面试
kYZEndedPosition //已结束
};
//审核状态
typedef NS_ENUM(NSUInteger, YZResumeState) {
kResumeStatePass = 1, //审核通过
kResumeStateinReview, //审核中
kResumeStateFail //审核未通过
};
//反馈类型
typedef NS_ENUM(NSUInteger, YZFeedBackType) {
kYZFeedBackSuggest = 1,
kYZFeedBackBUG,
kYZFeedBackOther
};
//用户身份
typedef NS_ENUM(NSUInteger, YZUserType) {
kYZUsrTypeNone = 0, //没有选择用户身份
kYZUserType, //用户版
kYZCompanyType //企业版
};
typedef NS_ENUM(NSUInteger, YZBannerType) {
kCommonWebType = 1, //普通跳转网页
kPostDetailType, //职位详情
kResumeDetailType, //简历详情
kCreateResumeType //制作或完善简历
};
//选择查看的职位类型
typedef NS_ENUM(NSUInteger, YZPostState) {
kYZReviewPost = 0, //审核中
kYZProcessingPost = 1, //发布中
kYZOverPost = 3, //已结束
kYZFailedPost = 4 //审核未通过
};
//选择出行导航工具类型
typedef NS_ENUM(NSUInteger, YZTraveToolTypeForNavigation) {
kYZDriveForNavigation = 0, //驾车
kYZBusForNavigation, //公交
kYZWalkForNavigation //步行
};
typedef void(^YZMapNavigationBlock)(YZTraveToolTypeForNavigation type);
#endif /* YZConfig_h */
5、Vender
这部分是用于管理项目中使用到的常被修改和自定义的第三方库。
6、Resource
从名字很容易理解到,就是放项目中用到的资源文件,除开image放置在Assets.xcassets中,预配置的本地音频、plist、json均放在这个目录之下。
当然这是我的个人习惯,每个人都有自己的一套命名和规范,只要足够的清晰都是可以接受的。干净分明的文件结构层次,某种程度上也有助于开发过程中业务功能的分析,便于将封装的工具类剥离业务而独立开来,降低各个模块之间的粘性,从而提高复用性。而且这个过程在搭建项目时就要考虑的,也在一定程度上能反映开发人员是否具有一定的前瞻性和架构思维。目前,这也是我很需要努力的一个方向~