組件化
隨著代碼量程序和業(yè)務(wù)越來(lái)越多歪沃,最初的架構(gòu)不能適應(yīng)公司業(yè)務(wù)發(fā)展的速度竣蹦,解決辦法就是進(jìn)行項(xiàng)目的重構(gòu)筝野,前面的培訓(xùn)中介紹過(guò)單工程+MVC或單工程+MVVM等架構(gòu)晌姚,但是更加大型的項(xiàng)目,例如蘑菇街歇竟、淘寶挥唠,單工程的架構(gòu)是無(wú)法滿足架構(gòu)需求的,因此焕议,今天我們來(lái)了解一下組件化開(kāi)發(fā)宝磨。
本文主要介紹在登錄模塊組件化的基本流程以及遇到的一些困難和解決方案。
我理解的組件化有幾個(gè)原則盅安,組件內(nèi)部高聚合唤锉,組件之間無(wú)耦合,組件實(shí)現(xiàn)一個(gè)完整的功能以供外部調(diào)用别瞭。
中間件
在這次預(yù)研中窿祥,使用的是casa的中間件CTMediator,中間件采用CTMediator蝙寨,CTMediator主要采用target-action的調(diào)用方式晒衩。在我的理解中,target主要是指一整個(gè)模塊墙歪,如登錄模塊听系、用戶模塊、小游戲模塊虹菲,即時(shí)通訊模塊等等靠胜,action則為模塊內(nèi)部的調(diào)用方法,如獲取登錄界面、獲取注冊(cè)界面或者查詢信息等等浪漠。需要傳入的參數(shù)以param = demoParam的方式作為url的一部分傳入菠赚,在獲取到url后進(jìn)行url解析獲取具體執(zhí)行的方法。以前有讀過(guò)一篇文章提到:
在模塊內(nèi)部的界面跳轉(zhuǎn)也建議采用url轉(zhuǎn)發(fā)的模式郑藏,以便于外部可以直接使用url調(diào)用內(nèi)部界面。
雖然這個(gè)也不是很理解為什么...先暫且這么認(rèn)為吧瘩欺。
執(zhí)行target-action部分的代碼如下:
/*
scheme://[target]/[action]?[params]
url sample:
aaa://targetA/actionB?id=1234
*/
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params
{
NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
Class targetClass = NSClassFromString(targetClassString);
id target = [[targetClass alloc] init];
SEL action = NSSelectorFromString(actionString);
if (target == nil) {
// 這里是處理無(wú)響應(yīng)請(qǐng)求的地方之一必盖,這個(gè)demo做得比較簡(jiǎn)單,如果沒(méi)有可以響應(yīng)的target俱饿,就直接return了歌粥。實(shí)際開(kāi)發(fā)過(guò)程中是可以事先給一個(gè)固定的target專門用于在這個(gè)時(shí)候頂上,然后處理這種請(qǐng)求的
return nil;
}
if ([target respondsToSelector:action]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
} else {
// 這里是處理無(wú)響應(yīng)請(qǐng)求的地方拍埠,如果無(wú)響應(yīng)失驶,則嘗試調(diào)用對(duì)應(yīng)target的notFound方法統(tǒng)一處理
SEL action = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
} else {
// 這里也是處理無(wú)響應(yīng)請(qǐng)求的地方,在notFound都沒(méi)有的時(shí)候枣购,這個(gè)demo是直接return了嬉探。實(shí)際開(kāi)發(fā)過(guò)程中,可以用前面提到的固定的target頂上的棉圈。
return nil;
}
}
}
登錄模塊組件
內(nèi)部需要集成普通登錄功能涩堤、第三方登錄功能、注冊(cè)功能和修改密碼功能分瘾,共四個(gè)部分胎围。對(duì)于普通登錄功能,通過(guò)網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)德召,對(duì)于第三方登錄功能白魂,在我們的項(xiàng)目中涉及到微信、QQ和新浪微博三種登錄方式上岗,集成第三方平臺(tái)時(shí)需要注意url type福荸、url scheme的配置,同時(shí)根據(jù)三個(gè)平臺(tái)的要求鏈接系統(tǒng)庫(kù)液茎。
調(diào)用登錄模塊時(shí)判斷是否已經(jīng)登錄過(guò)逞姿,若登錄過(guò)則直接跳轉(zhuǎn)到詳情頁(yè),未登錄則跳轉(zhuǎn)到登錄界面進(jìn)行登錄捆等,成功后跳轉(zhuǎn)到詳情頁(yè)滞造。
- 普通登錄
- 第三方登錄
- 注冊(cè)
- 修改密碼
登錄模塊的打包
登錄模塊在打包過(guò)程中遇到很多問(wèn)題,首先是第三方庫(kù)的打包栋烤,一開(kāi)始我的第三方登錄功能在cocoapods直接調(diào)用了shareSDK的第三方登錄谒养,打包成庫(kù)之后出現(xiàn)了平臺(tái)Connector庫(kù)的dylib not load,image not found的問(wèn)題,由于自己也不太懂庫(kù)的加載的問(wèn)題买窟,加上這個(gè)庫(kù)又不是自己寫的不好控制和修改丰泊,所以就放棄直接集成shareSDK的第三方登錄功能,采用自己實(shí)現(xiàn)的方式始绍,在寫模塊時(shí)包含第三方平臺(tái)瞳购,打包時(shí)不打包平臺(tái),調(diào)用時(shí)引用這三個(gè)平臺(tái)庫(kù)即可亏推。Q!吞杭!由于打包動(dòng)態(tài)庫(kù)方法不同盏浇,所以我在自己調(diào)用第三方平臺(tái)打包調(diào)用成功后又試了一次使用ShareSDK,結(jié)果成功了芽狗,所以可能是前面生成庫(kù)的時(shí)候?qū)戝e(cuò)绢掰,自己調(diào)用庫(kù)總是有各種各樣的問(wèn)題,所以我還是使用ShareSDK集成吧童擎。
打包庫(kù)的時(shí)候在LeoLei的這篇文章上找到了非常好的方法滴劲,解決了一連串問(wèn)題,掛出來(lái)表示超級(jí)感謝顾复!
還有一個(gè)記錄的小技巧哑芹,在創(chuàng)建Framework時(shí)的工程名和最后生成的framework名字可以不一致,設(shè)置方法為Build Setting中Basic一欄捕透,修改Product Name聪姿,之前記得怎么設(shè)置,后來(lái)忘記了乙嘀,所以記錄在這里以免又忘記末购。