基礎(chǔ)構(gòu)想將現(xiàn)有的app維護(hù)好,以上一個(gè)版本的app為模版創(chuàng)建多個(gè)app給租戶使用
需求: 1.現(xiàn)有app 為模版 里面涉及的有關(guān)現(xiàn)有App的圖片字樣 要使用boundle包裝起來(lái)
并創(chuàng)建一個(gè)全局文件替換字樣
2.有關(guān)推送分享登陸模塊創(chuàng)建confige配置文件 使租戶可以使用自己的賬戶
3.因?yàn)榇罅孔鈶魺o(wú)須有高度自定義話的內(nèi)容所以初步模版不考慮配置不同的控件頁(yè)面樣式 只需要能替換appid icon name 和一些主題色就好
根據(jù)需求思考方案:可以簡(jiǎn)化開(kāi)發(fā)步驟 通過(guò)創(chuàng)建多個(gè)target創(chuàng)建大量相似項(xiàng)目 (可能可以使用腳本替換)
如圖步驟 你就可以生成2個(gè)包名不同的APP了
但是根據(jù)需求我們還需要查找出有關(guān)現(xiàn)有app的圖片文字進(jìn)行替換
以及有關(guān)推送分享登陸模塊創(chuàng)建confige配置文件 使租戶可以使用自己的賬戶
然后通過(guò) 讀取項(xiàng)目配置做差異化
.h
#import <Foundation/Foundation.h>
@class ArchConfigAccount;
/**
* 全部配置文件,主要用來(lái)存儲(chǔ)不同平行學(xué)院中的關(guān)于分享,友盟淹仑,以及服務(wù)器配置
*/
@interface ArchConfig : NSObject
+ (ArchConfig *)sharedInstance;
@property (nonatomic, strong, readonly) NSString *serverUrl;
@property (nonatomic, strong, readonly) NSString *chineseName;
@property (nonatomic, strong, readonly) NSString *englishName;
////////////////////分享相關(guān)////////////////////
//關(guān)于我們中,分享的描述語(yǔ)句
@property (nonatomic, strong, readonly) NSString *aboutShareDescription;
//學(xué)院微博賬號(hào)
@property (nonatomic, strong, readonly) NSString *weiboAccount;
////////////////////第三方Key等////////////////////
//數(shù)據(jù)統(tǒng)計(jì)肺孵,友盟
@property (nonatomic, strong, readonly) ArchConfigAccount *umeng;
@property (nonatomic, strong, readonly) ArchConfigAccount *wechat;
@property (nonatomic, strong, readonly) ArchConfigAccount *weibo;
@property (nonatomic, strong, readonly) ArchConfigAccount *qq;
@property (nonatomic, strong, readonly) ArchConfigAccount *share;
//信鴿推送
@property (nonatomic, strong, readonly) ArchConfigAccount *xgPush;
//ShareSDK 短信驗(yàn)證
@property (nonatomic, strong, readonly) ArchConfigAccount *sms;
////////////////////UI相關(guān)////////////////////
//側(cè)邊欄匀借,欄目列表
@property (nonatomic, strong, readonly) NSArray *tabsArray;
@property (nonatomic, strong, readonly) NSString *openUpBackgroundImagePath;
@property (nonatomic, strong, readonly) NSString *openUpLogoImagePath;
@property (nonatomic, strong, readonly) NSString *loginBackgroundImagePath;
@property (nonatomic, strong, readonly) NSString *sideVCBackgroundImagePath;
@property (nonatomic, strong, readonly) NSString *userBackgroundImagePath;
@property (nonatomic, strong, readonly) NSString *defaultPortraitImagePath;
//系統(tǒng)默認(rèn)配色
@property (nonatomic, strong, readonly) UIColor *appColor;
@property (nonatomic, strong, readonly) NSString *appId;
@property (nonatomic, strong, readonly) NSString *loginTextStyle;
@property (nonatomic, strong, readonly) NSString *aboutUsShareImagePath;
//當(dāng)前平行學(xué)院使用前綴
- (NSString *)prefix;
- (NSString *)getResourcePath:(NSString *)resourceName withSuffix:(NSString *)suffix;
- (NSString *)getResourcePath:(NSString *)resourceName;
@end
@interface ArchConfigAccount : NSObject
@property (nonatomic, strong) NSString *appID;
@property (nonatomic, strong) NSString *appKey;
@property (nonatomic, strong) NSString *appSecret;
@property (nonatomic, strong) NSString *callbackUrl;
- (id)initWithDictionary:(NSDictionary *)dic;
@end
.m
#import "ArchConfig.h"
#import "UIColor+Ext.h"
static NSString *kServerAddressKey = @"ServerAddress";
static NSString *kUMengKey = @"UMeng";
static NSString *kXGPush = @"XGPush";
static NSString *kSocialAccountKey = @"SocialAccount";
static NSString *kSMSKey = @"SMS";
static NSString *kShareSDK = @"ShareSDK";
static NSString *kTabKey = @"Tabs";
static NSString *kChineseNameKey = @"ChineseName";
static NSString *kEnglishNameKey = @"EnglishName";
static NSString *kAboutShareDescriptionKey = @"AboutShareDescription";
static NSString *kAppIDKey = @"AppID";
static NSString *kAppColorKey = @"AppColor";
static NSString *kWeiboAccountKey = @"WeiboAccount";
static NSString *kLoginTextStyle = @"LoginTextStyle";
static NSString *kaboutUsShareImage = @"aboutUsShareImage";
@interface ArchConfig()
@property (nonatomic, strong, readwrite) ArchConfigAccount *umeng;
@property (nonatomic, strong, readwrite) ArchConfigAccount *wechat;
@property (nonatomic, strong, readwrite) ArchConfigAccount *weibo;
@property (nonatomic, strong, readwrite) ArchConfigAccount *qq;
@property (nonatomic, strong, readwrite) ArchConfigAccount *xgPush;
@property (nonatomic, strong, readwrite) ArchConfigAccount *sms;
@property (nonatomic, strong, readwrite) ArchConfigAccount *share;
@property (nonatomic, strong, readwrite) UIColor *appColor;
@property (nonatomic, strong, readwrite) NSArray *tabsArray;
@property (nonatomic, strong, readwrite) NSString *openUpBackgroundImagePath;
@property (nonatomic, strong, readwrite) NSString *openUpLogoImagePath;
@property (nonatomic, strong, readwrite) NSString *loginBackgroundImagePath;
@property (nonatomic, strong, readwrite) NSString *sideVCBackgroundImagePath;
@property (nonatomic, strong, readwrite) NSString *userBackgroundImagePath;
@property (nonatomic, strong, readwrite) NSString *defaultPortraitImagePath;
@property (nonatomic, strong, readwrite) NSString *appId;
@property (nonatomic, strong, readwrite) NSString *chineseName;
@property (nonatomic, strong, readwrite) NSString *englishName;
@property (nonatomic, strong, readwrite) NSString *weiboAccount;
@property (nonatomic, strong, readwrite) NSString *aboutShareDescription;
@property (nonatomic, strong, readwrite) NSString *aboutUrl;
@property (nonatomic, strong, readwrite) NSString *serverUrl;
@property (nonatomic, strong, readwrite) NSString *loginTextStyle;
@property (nonatomic, strong, readwrite) NSString *aboutUsShareImagePath;
@end
#pragma mark - ArchConfig
@implementation ArchConfig
+ (id)sharedInstance{
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
- (id)init{
self = [super init];
if (self) {
NSString *fileName = @"config.plist";
NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:[self getResourcePath:fileName]];
[self setupData:dic];
self.openUpLogoImagePath = [self getResourcePath:@"openUpLogo.png"];
self.openUpBackgroundImagePath = [self getResourcePath:@"openUpBackground.jpg"];
self.sideVCBackgroundImagePath = [self getResourcePath:@"sideVCBackground" withSuffix:@"png"];
self.loginBackgroundImagePath = [self getResourcePath:@"loginBackground" withSuffix:@"jpg"];
self.userBackgroundImagePath = [self getResourcePath:@"userBackground" withSuffix:@"png"];
self.defaultPortraitImagePath = [self getResourcePath:@"defaultPortrait" withSuffix:@"jpg"];
self.aboutUsShareImagePath = [self getResourcePath:@"aboutUsShare" withSuffix:@"jpg"];
}
return self;
}
- (NSString *)getResourcePath:(NSString *)resourceName withSuffix:(NSString *)suffix{
NSString *folderPath = [NSString stringWithFormat:@"Colleges/%@/",@AppPrefix];
NSString *filePath = [[NSBundle mainBundle] pathForResource:resourceName ofType:suffix inDirectory:folderPath];
//如果圖片,先檢測(cè)是否有圖片平窘,如果沒(méi)有吓肋,查找@2x,@3x
if ([suffix isEqualToString:@"png"] || [suffix isEqualToString:@"jpg"]) {
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
return filePath;
}else{
NSString *fileName = [NSString stringWithFormat:@"%@%@",resourceName,[self imageSuffixForDevice]];
filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:suffix inDirectory:folderPath];
return filePath;
}
}
return filePath;
}
- (NSString *)getResourcePath:(NSString *)resourceName{
return [self getResourcePath:resourceName withSuffix:nil];
}
#pragma mark - Private
- (void)setupData:(NSDictionary *)dic{
self.chineseName = [dic objectForKey:kChineseNameKey];
self.englishName = [dic objectForKey:kEnglishNameKey];
self.aboutShareDescription = [dic objectForKey:kAboutShareDescriptionKey];
self.appId = [dic objectForKey:kAppIDKey];
self.weiboAccount = [dic objectForKey:kWeiboAccountKey];
self.loginTextStyle = [dic objectForKey:kLoginTextStyle];
NSString *colorStr = [dic objectForKey:kAppColorKey];
if (colorStr) {
self.appColor = [UIColor colorWithRGBString:colorStr];
}
self.tabsArray = [dic objectForKey:kTabKey];
NSDictionary *umeng = [dic objectForKey:kUMengKey];
self.umeng = [[ArchConfigAccount alloc] initWithDictionary:umeng];
if ([self.umeng.appKey isNull]) {
DDLogError(@"友盟AppKey為空");
}
self.serverUrl = [dic objectForKey:kServerAddressKey];
if ([self.serverUrl isNull]) {
DDLogError(@"服務(wù)器地址為空");
}
NSDictionary *xgPush = [dic objectForKey:kXGPush];
self.xgPush = [[ArchConfigAccount alloc] initWithDictionary:xgPush];
if ([self.xgPush.appKey isNull] || [self.xgPush.appID isNull]) {
DDLogError(@"信鴿AppID或AppKey為空");
}
NSDictionary *sms = [dic objectForKey:kSMSKey];
self.sms = [[ArchConfigAccount alloc] initWithDictionary:sms];
if ([self.sms.appKey isNull] || [self.sms.appSecret isNull]) {
DDLogError(@"SMS AppKey或AppSecret為空");
}
NSDictionary *share = [dic objectForKey:kShareSDK];
self.share = [[ArchConfigAccount alloc] initWithDictionary:share];
if ([self.share.appKey isNull]) {
DDLogError(@"ShareSDK AppKey為空");
}
NSDictionary *social = [dic objectForKey:kSocialAccountKey];
self.wechat = [[ArchConfigAccount alloc] initWithDictionary:[social objectForKey:@"wechat"]];
self.qq = [[ArchConfigAccount alloc] initWithDictionary:[social objectForKey:@"qq"]];
self.weibo = [[ArchConfigAccount alloc] initWithDictionary:[social objectForKey:@"weibo"]];
if (self.tabsArray.count==0) {
DDLogError(@"側(cè)邊欄不能為空");
}
}
#pragma mark - Public
- (NSString *)prefix{
return @AppPrefix;
}
@end
#pragma mark - ArchConfigAccount
@implementation ArchConfigAccount
- (id)initWithDictionary:(NSDictionary *)dic{
self = [super init];
if (self) {
self.appID = [dic objectForKey:@"id"];
self.appKey = [dic objectForKey:@"key"];
self.appSecret = [dic objectForKey:@"secret"];
self.callbackUrl = [dic objectForKey:@"callback"];
}
return self;
}
@end
之后通過(guò)讀取文件取得個(gè)性化定制
但是此方式圖片處理不是很好如果圖片過(guò)多較難處理
思路通過(guò)唐橋猿題庫(kù)的博客
在Xcode的一個(gè)項(xiàng)目中,可以允許建立多個(gè)編譯的target瑰艘,每個(gè)target代表著最終編譯出來(lái)的一個(gè)App文件是鬼,在每個(gè)target中,可以添加不同的編譯源文件和資源文件紫新。最終均蜜,通過(guò)我們?cè)诓煌瑃arget之間,修改其 Copy Bundle Resources 和 Compile Sources 配置芒率,使課程之間的差異性得到實(shí)現(xiàn)囤耳。我們具體的配置方案如下:
我們的每個(gè)課程的資源文件都具有相同的文件名,例如首頁(yè)背景都叫 HomeBackgroundBg.png 偶芍,由于每個(gè)課程背景不一樣紫皇,所以我們?cè)诠こ讨校恳粋€(gè)課程target下腋寨,通過(guò)修改Copy Bundle Resources,使其都配置有不同的(但是同名) HomeBackgroundBg.png 化焕。這樣的好處是萄窜,在代碼邏輯層面,我們可以完全不用處理課程間資源文件的差異性問(wèn)題撒桨。資源文件的差異性都是通過(guò)配置文件來(lái)保證的查刻。
對(duì)于文案一類的差別,我們通過(guò)修改Compile Sources凤类,使不同的課程有著不同的文案定義文件穗泵。通過(guò)這樣,我們使不同課程有了不同的文案谜疤。另外包括后臺(tái)網(wǎng)絡(luò)接口的差異性問(wèn)題佃延,統(tǒng)計(jì)項(xiàng)的差異性問(wèn)題现诀,也都是這樣處理的。
如此簡(jiǎn)易版的多target 相似項(xiàng)目也就又了一定的可行性