基础构想将现有的app维护好,以上一个版本的app为模版创建多个app给租户使用
需求: 1.现有app 为模版 里面涉及的有关现有App的图片字样 要使用boundle包装起来
并创建一个全局文件替换字样
2.有关推送分享登陆模块创建confige配置文件 使租户可以使用自己的账户
3.因为大量租户无须有高度自定义话的内容所以初步模版不考虑配置不同的控件页面样式 只需要能替换appid icon name 和一些主题色就好
根据需求思考方案:可以简化开发步骤 通过创建多个target创建大量相似项目 (可能可以使用脚本替换)
如图步骤 你就可以生成2个包名不同的APP了
但是根据需求我们还需要查找出有关现有app的图片文字进行替换
以及有关推送分享登陆模块创建confige配置文件 使租户可以使用自己的账户
然后通过 读取项目配置做差异化
.h
#import <Foundation/Foundation.h>
@class ArchConfigAccount;
/**
* 全部配置文件,主要用来存储不同平行学院中的关于分享,友盟,以及服务器配置
*/
@interface ArchConfig : NSObject
+ (ArchConfig *)sharedInstance;
@property (nonatomic, strong, readonly) NSString *serverUrl;
@property (nonatomic, strong, readonly) NSString *chineseName;
@property (nonatomic, strong, readonly) NSString *englishName;
////////////////////分享相关////////////////////
//关于我们中,分享的描述语句
@property (nonatomic, strong, readonly) NSString *aboutShareDescription;
//学院微博账号
@property (nonatomic, strong, readonly) NSString *weiboAccount;
////////////////////第三方Key等////////////////////
//数据统计,友盟
@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 短信验证
@property (nonatomic, strong, readonly) ArchConfigAccount *sms;
////////////////////UI相关////////////////////
//侧边栏,栏目列表
@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;
//系统默认配色
@property (nonatomic, strong, readonly) UIColor *appColor;
@property (nonatomic, strong, readonly) NSString *appId;
@property (nonatomic, strong, readonly) NSString *loginTextStyle;
@property (nonatomic, strong, readonly) NSString *aboutUsShareImagePath;
//当前平行学院使用前缀
- (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];
//如果图片,先检测是否有图片,如果没有,查找@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(@"服务器地址为空");
}
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(@"侧边栏不能为空");
}
}
#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
之后通过读取文件取得个性化定制
但是此方式图片处理不是很好如果图片过多较难处理
思路通过唐桥猿题库的博客
在Xcode的一个项目中,可以允许建立多个编译的target,每个target代表着最终编译出来的一个App文件,在每个target中,可以添加不同的编译源文件和资源文件。最终,通过我们在不同target之间,修改其 Copy Bundle Resources 和 Compile Sources 配置,使课程之间的差异性得到实现。我们具体的配置方案如下:
我们的每个课程的资源文件都具有相同的文件名,例如首页背景都叫 HomeBackgroundBg.png ,由于每个课程背景不一样,所以我们在工程中,每一个课程target下,通过修改Copy Bundle Resources,使其都配置有不同的(但是同名) HomeBackgroundBg.png 。这样的好处是,在代码逻辑层面,我们可以完全不用处理课程间资源文件的差异性问题。资源文件的差异性都是通过配置文件来保证的。
对于文案一类的差别,我们通过修改Compile Sources,使不同的课程有着不同的文案定义文件。通过这样,我们使不同课程有了不同的文案。另外包括后台网络接口的差异性问题,统计项的差异性问题,也都是这样处理的。
如此简易版的多target 相似项目也就又了一定的可行性