最近項目處於測試階段,所以免不了每天都得打包給測試人員,由於我們公司規模比較大,項目環境也分為了三種:測試環境、預上線(預生產)環境、上線(生產)環境。所以每到了測試后期,每天打包的時間也占了不少,遇見筆記本內存不足、xcode鬧脾氣或者有緊急解決的bug,打包更是一件很折磨人的活。最近兩天測試到了尾聲,終於有了時間,突然有個想法,那就是有沒有什么辦法,一份源碼打包可以快速的切換環境供測試人員測試。而且在上家公司,也出現過這個需求,只是當時沒怎么重視,慢慢的就被忽略了。簡單說明下,我們公司預上線環境和上線環境源碼是一套的,只不過預上線環境在hosts增加了綁定的地址。所以下面只講切換測試環境和預上線環境,了解了下面的方法,有多少種環境的切換都不是問題。
原先我的項目切換環境,是根據pch文件里的一個宏定義,手動改為0或者1來決定是什么環境,然后在一個專門放項目請求地址基礎url串的文件里,根據不同的環境拼接出不同的url,所以才會有不同的環境有不同的請求url。所以為了避免每次切換環境都得重新打包,網上也看了不少方法,但是都好復雜,還需要動項目target中的設置,覺得太麻煩,最終想到的解決思路是,在登錄頁面放一個按鈕,點擊這個按鈕顯示UIAlertSheet,可以手動選擇切換需要的環境,並且着重顯示當前所處的環境。將切換好的環境保存在偏好設置里,然后在專門放項目請求地址基礎url串的文件里,取出存放在偏好設置的值並且拼接出需要的url,考慮到在登錄頁面出現之前就有了接口請求或者對接口請求url的基本設置,所以最好是在選擇所需的環境后,重啟app以確保切換成功。不再多說,上代碼:
1.在pch文件里,定義一些常用的宏
/***************單例模式宏**************/ #define MACRO_SHARED_INSTANCE_INTERFACE +(instancetype)sharedInstance; #define MACRO_SHARED_INSTANCE_IMPLEMENTATION(CLASS) \ +(instancetype)sharedInstance \ { \ static CLASS * sharedInstance = nil; \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ sharedInstance = [[CLASS alloc] init]; \ }); \ return sharedInstance; \ } #define APPDelegate ((AppDelegate*)[UIApplication sharedApplication].delegate) #define kBaseUrlSubStringKey @"kBaseUrlSubStringKey" #define kApp_WebSocket_URLKey @"kApp_WebSocket_URLKey" #define kServerFBKey @"serverFBKey" #pragma mark - 偏好讀寫/****************************/ #define KYMWriteUserDefaults(value, key) [[NSUserDefaults standardUserDefaults] setObject:value forKey:key] #define KYMReadUserDefaults(key) [[NSUserDefaults standardUserDefaults]objectForKey:key] #define KYMRemoveUserDefaults(key) [[NSUserDefaults standardUserDefaults] removeObjectForKey:key] #define KYMSaveUserDefaults [[NSUserDefaults standardUserDefaults] synchronize]
2.創建一個工具類,用來切換環境和獲得當前環境
#import <Foundation/Foundation.h> @interface YimaiChangeEnvironment : NSObject MACRO_SHARED_INSTANCE_INTERFACE //切換環境 - (void)changeEnvironment; //獲得當前環境 - (NSString *)currentEnvironment; @end
#import "YimaiChangeEnvironment.h" #import "AppDelegate.h" #import "IQUIWindow+Hierarchy.h" //TEST static NSString *const devConfig = @"0"; //預生產 static NSString *const prodConfig = @"1"; //生產 //static NSString *const prodConfig1 = @"2"; @implementation YimaiChangeEnvironment MACRO_SHARED_INSTANCE_IMPLEMENTATION(YimaiChangeEnvironment) //切換環境 - (void)changeEnvironment { NSLog(@"change environment start"); NSString *title=@"切換環境"; NSString *subTitle=@"重啟后生效, 非測試人員請點擊cancel"; UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:subTitle preferredStyle:UIAlertControllerStyleActionSheet]; //修改title NSMutableAttributedString *alertControllerStr = [[NSMutableAttributedString alloc] initWithString:title]; // [alertControllerStr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, alertControllerStr.length)]; [alertControllerStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20] range:NSMakeRange(0, alertControllerStr.length)]; [alert setValue:alertControllerStr forKey:@"attributedTitle"]; //修改message NSMutableAttributedString *alertControllerMessageStr = [[NSMutableAttributedString alloc] initWithString:subTitle]; // [alertControllerMessageStr addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(0, alertControllerMessageStr.length)]; [alertControllerMessageStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, alertControllerMessageStr.length)]; [alert setValue:alertControllerMessageStr forKey:@"attributedMessage"]; NSString *currentEnvironment=@""; if ([[self currentEnvironment] isEqualToString:devConfig]) { currentEnvironment=@"當前環境為 TEST"; [alert addAction:[UIAlertAction actionWithTitle:@"TEST" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { //測試環境 [[NSUserDefaults standardUserDefaults] setObject:devConfig forKey:kServerFBKey]; //重置請求的基url [self resetRequestBaseUrl]; }]]; [alert addAction:[UIAlertAction actionWithTitle:@"預生產" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { //預生產環境 [[NSUserDefaults standardUserDefaults] setObject:prodConfig forKey:kServerFBKey]; //重置請求的基url [self resetRequestBaseUrl]; }]]; // [alert addAction:[UIAlertAction actionWithTitle:@"生產" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // //生產環境 // [[NSUserDefaults standardUserDefaults] setObject:prodConfig1 forKey:kServerFBKey]; // }]]; } else if ([[self currentEnvironment] isEqualToString:prodConfig]) { currentEnvironment=@"當前環境為 預生產"; [alert addAction:[UIAlertAction actionWithTitle:@"TEST" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { //測試環境 [[NSUserDefaults standardUserDefaults] setObject:devConfig forKey:kServerFBKey]; //重置請求的基url [self resetRequestBaseUrl]; }]]; [alert addAction:[UIAlertAction actionWithTitle:@"預生產" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { //預生產環境 [[NSUserDefaults standardUserDefaults] setObject:prodConfig forKey:kServerFBKey]; //重置請求的基url [self resetRequestBaseUrl]; }]]; // [alert addAction:[UIAlertAction actionWithTitle:@"生產" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // //生產環境 // [[NSUserDefaults standardUserDefaults] setObject:prodConfig1 forKey:kServerFBKey]; // }]]; } [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { // }]]; NSLog(@"currentEnvironment = %@", currentEnvironment); //當前選擇的視圖控制器需要自己賦值,比如tabbar的didSelectViewController里 [KeyWindow.currentViewController presentViewController:alert animated:YES completion:^{ }]; } //獲得當前環境 - (NSString *)currentEnvironment{ //默認測試環境 NSString *currentEnvironment=devConfig; if ([[NSUserDefaults standardUserDefaults] objectForKey:kServerFBKey]) { currentEnvironment=[[NSUserDefaults standardUserDefaults] objectForKey:kServerFBKey]; }return currentEnvironment; } - (void)resetRequestBaseUrl { #pragma mark - 切換測試線和預生產環境 if ([[YimaiChangeEnvironment sharedInstance].currentEnvironment isEqualToString:@"0"]) { NSLog(@"測試環境。。。。。。。"); //測試環境 KYMWriteUserDefaults(@"test.", kBaseUrlSubStringKey); KYMWriteUserDefaults(@"ws://tws.rt.xywy.com/websocket", kApp_WebSocket_URLKey); KYMSaveUserDefaults; }else if ([[YimaiChangeEnvironment sharedInstance].currentEnvironment isEqualToString:@"1"]) { //預上線環境 KYMWriteUserDefaults(@"", kBaseUrlSubStringKey); KYMWriteUserDefaults(@"ws://testws.rt.xywy.com/websocket", kApp_WebSocket_URLKey); KYMSaveUserDefaults; NSLog(@"預生產環境........."); } } @end
3.在登錄頁面加入切換環境的入口
//點擊切換開發環境 - (IBAction)didClickChangeEnvironment:(id)sender { [[YimaiChangeEnvironment sharedInstance]changeEnvironment]; return; }