項(xiàng)目想做成電商app平臺(tái)

基礎(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)目 (可能可以使用腳本替換)

1.png

2.png

3.png

如圖步驟 你就可以生成2個(gè)包名不同的APP了
但是根據(jù)需求我們還需要查找出有關(guān)現(xiàn)有app的圖片文字進(jìn)行替換
以及有關(guān)推送分享登陸模塊創(chuàng)建confige配置文件 使租戶可以使用自己的賬戶

5.png

然后通過(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)目也就又了一定的可行性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末履肃,一起剝皮案震驚了整個(gè)濱河市仔沿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尺棋,老刑警劉巖封锉,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異膘螟,居然都是意外死亡成福,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門荆残,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奴艾,“玉大人,你說(shuō)我怎么就攤上這事脊阴∥詹啵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵嘿期,是天一觀的道長(zhǎng)品擎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)备徐,這世上最難降的妖魔是什么萄传? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蜜猾,結(jié)果婚禮上秀菱,老公的妹妹穿的比我還像新娘。我一直安慰自己蹭睡,他們只是感情好衍菱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著肩豁,像睡著了一般脊串。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上清钥,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天琼锋,我揣著相機(jī)與錄音,去河邊找鬼祟昭。 笑死缕坎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的篡悟。 我是一名探鬼主播谜叹,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼匾寝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了叉谜?” 一聲冷哼從身側(cè)響起旗吁,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎停局,沒(méi)想到半個(gè)月后很钓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡董栽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年码倦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锭碳。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袁稽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出擒抛,到底是詐尸還是另有隱情推汽,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布歧沪,位于F島的核電站歹撒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诊胞。R本人自食惡果不足惜暖夭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撵孤。 院中可真熱鬧迈着,春花似錦、人聲如沸邪码。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闭专。三九已至奴潘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喻圃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工粪滤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斧拍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓杖小,卻偏偏與公主長(zhǎng)得像肆汹,于是被迫代替她去往敵國(guó)和親愚墓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容