開發(fā)是個持續(xù)性的過程,無論項目大小,都需要一套嚴(yán)格的開發(fā)規(guī)范。遵守規(guī)范的好處,自然不用多說,我只想就項目開發(fā)中的代碼文件結(jié)構(gòu)談?wù)勛约旱睦斫狻?/p>
先來看看下面這張圖吧,這是公司目前的一個項目,框架是我搭建的,在項目啟動前期,我將文件分為如下六大類:(注明:YZ是項目的縮寫前綴)
1、AppDelegate
放置AppDelegate文件,有時候項目會需要自定義自己的AppDelegate來處理更多的消息通知類的東西。
2、Main
主要放的是項目的每個模塊對應(yīng)的代碼。因為本項目是用戶端和企業(yè)端互相切換身份而共存的,所以Main下面我分為:Company和User,并在相應(yīng)目錄下新增各自的業(yè)務(wù)功能頁面
3、Common
是項目中通用的模塊,Model & View & VC的集合。
4、Expand
放置的是宏定義、封裝好的網(wǎng)絡(luò)和工具、分類、常量定義等。其中就Const和Macros文件夾下子目錄做介紹:
1)Const:該文件夾下放置了YZConst類, 定義了App相關(guān)的常量和通知、userDefault名稱
2)Macros:包含YZHeader.h、YZNetUrlConfig.h、YZDefine.h、YZConfig.h四個頭文件。前兩個分別是添加常用頭文件需要#import的類和定義所有的網(wǎng)絡(luò)請求地址,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;
//單例對象實現(xiàn)
#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);
//刷新企業(yè)基礎(chǔ)信息回調(diào)
typedef void(^YZReloadCompanyInfoComplete)();
//職位詳情的初始化完成回調(diào)
typedef void(^YZResumeDetailVCInitComplete)();
typedef void(^YZCreatePostInitComplete)();
/*
* 枚舉類型定義
*/
typedef NS_ENUM(NSInteger, YZBarItemPostion) {
YZBarItemPostionLeft = 0,
YZBarItemPostionRight
};
//網(wǎng)絡(luò)狀態(tài)
typedef NS_ENUM(NSInteger, YZNetReachabilityStatus) {
kYZNetReachabilityStatusUnknown = -1,
kYZNetReachabilityStatusNotReachable,
kYZNetReachabilityStatusReachableViaWWAN,
kYZNetReachabilityStatusReachableViaWiFi
};
//網(wǎng)絡(luò)狀態(tài)回調(diào)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, //公司區(qū)域ID
kYZCompanyInfoProvName, //公司的省
kYZCompanyInfoCityName, //公司市
kYZCompanyInfoAddress, //公司詳細地址
kYZCompanyInfoState, //公司審核狀態(tài)(狀態(tài)0:審核中,1:正常,2:封號,3未通過)
kYZCompanyInfoJobCount, //公司發(fā)布崗位數(shù)
kYZCompanyInfoUserAvater,//公司頭像
kYZCompanyInfoUserName, //公司注冊時填寫的用戶名
kYZCompanyInfoLinkCount //公司已與用戶聊天個數(shù)
};
typedef NS_ENUM(NSUInteger, YZCompanyReviewState) {
YZCompanyInReview = 0, //審核中
YZCompanyInNormal, //正常
YZCompanyInBlock, //封號
YZCompanyInFail //未通過
};
typedef NS_ENUM(NSUInteger, YZConfigType) {
YZConfigPostArray = 1, //職位
YZConfigSalary, //薪資
YZConfigDegree, //學(xué)歷
YZConfigSpecialtyTags, //個人標(biāo)簽和職位誘惑
//公共的配置configBase
YZConfigShareToFriend, //app分享給好友
YZConfigShareToZone, //app分享到朋友圈/QQ空間
YZConfigLoginShare, //第三方登陸和分享是否全部顯示,0不開啟,1全部顯示
YZConfigCurrentVersion, //服務(wù)器版本地址
YZConfigUpgradeVersionUrl, //升級的網(wǎng)址
YZConfigShouldForceUpgrade, //強制升級
YZConfigUpgradeDesc, //升級描述
YZConfigRouter, //跳轉(zhuǎn)url
YZConfigBackgroundMusic, //視頻背景音樂
YZConfigCompanyLinkLimit, //企業(yè)與用戶聊的限制
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 //視頻拼接
};
//錄像的狀態(tài)
typedef NS_ENUM(NSUInteger, YZRecordState) {
kYZRecordNone = 1,
kYZRecordStart, //開始錄制
kYZRecordPause, //暫停錄制
kYZRecordDone //完成錄制
};
//時間戳快速轉(zhuǎn)換為時間字符串
typedef NS_ENUM(NSUInteger, YZQuickFormatType) {
kYZQuickFormateTypeNone = 0, //自己定義轉(zhuǎn)換
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 //通告
};
//職位發(fā)布人類型
typedef NS_ENUM(NSUInteger, kYZPositionPublisherType) {
kYZPersonalPublisher, //個人
kYZEnterprisePublisher //企業(yè)
};
//錄制的方案
typedef NS_ENUM(NSUInteger, YZRecordType) {
kYZRecordVedio = 1, //錄制
kYZChangeVedio //重錄
};
//圖片裁剪類型
typedef NS_ENUM(NSUInteger, PhotoClipType) {
PhotoClipTypeCircle = 0,
PhotoClipTypeSquare
};
//已投遞的職位狀態(tài)
typedef NS_ENUM(NSUInteger, YZPostedPositionStatusType) {
kYZUninterviewPosition, //待面試
kYZEndedPosition //已結(jié)束
};
//審核狀態(tài)
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 //企業(yè)版
};
typedef NS_ENUM(NSUInteger, YZBannerType) {
kCommonWebType = 1, //普通跳轉(zhuǎn)網(wǎng)頁
kPostDetailType, //職位詳情
kResumeDetailType, //簡歷詳情
kCreateResumeType //制作或完善簡歷
};
//選擇查看的職位類型
typedef NS_ENUM(NSUInteger, YZPostState) {
kYZReviewPost = 0, //審核中
kYZProcessingPost = 1, //發(fā)布中
kYZOverPost = 3, //已結(jié)束
kYZFailedPost = 4 //審核未通過
};
//選擇出行導(dǎo)航工具類型
typedef NS_ENUM(NSUInteger, YZTraveToolTypeForNavigation) {
kYZDriveForNavigation = 0, //駕車
kYZBusForNavigation, //公交
kYZWalkForNavigation //步行
};
typedef void(^YZMapNavigationBlock)(YZTraveToolTypeForNavigation type);
#endif /* YZConfig_h */
5、Vender
這部分是用于管理項目中使用到的常被修改和自定義的第三方庫。
6、Resource
從名字很容易理解到,就是放項目中用到的資源文件,除開image放置在Assets.xcassets中,預(yù)配置的本地音頻、plist、json均放在這個目錄之下。
當(dāng)然這是我的個人習(xí)慣,每個人都有自己的一套命名和規(guī)范,只要足夠的清晰都是可以接受的。干凈分明的文件結(jié)構(gòu)層次,某種程度上也有助于開發(fā)過程中業(yè)務(wù)功能的分析,便于將封裝的工具類剝離業(yè)務(wù)而獨立開來,降低各個模塊之間的粘性,從而提高復(fù)用性。而且這個過程在搭建項目時就要考慮的,也在一定程度上能反映開發(fā)人員是否具有一定的前瞻性和架構(gòu)思維。目前,這也是我很需要努力的一個方向~