組件化

使用cocoapods創(chuàng)建自己的組件

命令行執(zhí)行pod lib creat 組件名命令,創(chuàng)建自己的組件唐责。然后就會(huì)讓你輸入一系列的配置:

What is your name? 
What is your email?
What platform do you want to use?? [ iOS / macOS ]
 > ios 

What language do you want to use?? [ Swift / ObjC ]
 > objc  

Would you like to include a demo application with your library? [ Yes / No ]
 > yes 

Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > none 

Would you like to do view based testing? [ Yes / No ]
 > no 

What is your class prefix?
 > ZF 

配置完成后御蒲,會(huì)自動(dòng)創(chuàng)建module以及測試的工程。創(chuàng)建的module目錄結(jié)構(gòu)如下:

module目錄結(jié)構(gòu)

Class目錄下放置module代碼,Assets目錄下放置module的資源文件间唉。Example目下是為我們創(chuàng)建的測試工程,在測試工程中引入了我們創(chuàng)建的module利术,來進(jìn)行測試呈野。然后我們將module相關(guān)的代碼放到Classes目錄下,切換到Example目錄下執(zhí)行pod install印叁,然后example工程會(huì)更新module代碼被冒,對(duì)module進(jìn)行測試使用。
如果我們創(chuàng)建的module依賴于其他的三方的module或者自己的私有module轮蜕,那么就應(yīng)該在我們創(chuàng)建的module工程的podspec文件配置依賴昨悼。例如依賴AFNetworkingMasonry跃洛,ZFTestModel率触,配置依賴和頭文件如下:

s.dependency 'AFNetworking'
s.dependency 'Masonry'
s.dependency 'ZFTestModel'
s.prefix_header_contents = '#import "Masonry.h"','#import "UIKit+AFNetworking.h"','#import "LGTest.h"'

這樣配置完成后還沒有結(jié)束,因?yàn)閆FTestModel是我們私有的module汇竭,cocoapods是無法直接通過spec找到的葱蝗,需要手動(dòng)配置我們的私有module查找路徑,在example工程的Podfile文件中指定:

pod 'ZFTestModule', :path => '../../ZFTestModule'

這樣配置完成后就可以在example工程中測試我們的module了细燎,執(zhí)行pod install两曼,然后就可以正常使用了。

注意點(diǎn):加載圖片或者json的時(shí)候玻驻,首先我們需要把圖片或者json文件放到我們上面提到的Assets文件中悼凑。然后在podspec中配置資源的查找路徑:

s.resource_bundles = {
     'LGModuleTest' => ['LGModuleTest/Assets/*']
   }

配置然后在加載資源(圖片、plist文件璧瞬、xib等)的時(shí)候需要制定bundle佛析。例如加載圖片:

NSString *bundlePath = [[NSBundle bundleForClass:[self class]].resourcePath stringByAppendingPathComponent:@"/LGModuleTest.bundle"];
NSBundle *resoure_bundle = [NSBundle bundleWithPath:bundlePath];
self.imageView.image = [UIImage imageNamed:@"share_wechat" inBundle:resoure_bundle compatibleWithTraitCollection:nil];

然后重新pod installl,執(zhí)行example工程彪蓬,就可以加載資源了寸莫。

CTMediator方式進(jìn)行模塊間通信

使用CTMediator可以在模塊間通過scheme的形式進(jìn)行通信,這樣就可以實(shí)現(xiàn)解耦合档冬。

scheme://[target]/[action]?[params]
url sample:
aaa://targetA/actionB?id=1234

1膘茎、處理scheme桃纯,將scheme中的target、action和params分離出來披坏;
2态坦、使用runtime生成對(duì)應(yīng)的target對(duì)象,action生成SEL;
3棒拂、如果返回值為基本數(shù)據(jù)類型和void使用NSInvocation實(shí)現(xiàn)對(duì)Target的SEL的調(diào)用伞梯,否則使用performSelector執(zhí)行對(duì)應(yīng)的SEL。

CTMediator屬于底層的基礎(chǔ)層帚屉,但是我們A和B模塊通信谜诫,比如A模塊要跳轉(zhuǎn)到B模塊的DetailViewController,需要引入DetailViewController攻旦,然后創(chuàng)建該視圖控制器進(jìn)行跳轉(zhuǎn)喻旷。或者A模塊需要對(duì)B模塊的一個(gè)視圖進(jìn)行賦值牢屋,也需要拿到B模塊的視圖且预,然后取出來參數(shù)進(jìn)行賦值。這些代碼不能包含在CTMediator層烙无,因?yàn)樗腔A(chǔ)模塊锋谐,不能包含業(yè)務(wù)代碼,不能對(duì)上層的業(yè)務(wù)代碼產(chǎn)生依賴截酷。那么此時(shí)就會(huì)有一個(gè)中間層Target-Action層涮拗。Target-Action是跟隨著業(yè)務(wù)模塊B進(jìn)行維護(hù)的,相當(dāng)于模塊B對(duì)外暴露的功能接口通過自己的Target-Action來提供合搅。
例如下面的TargetA

- (id)Action_configCell:(NSDictionary *)params
{
    NSString *title = params[@"title"];
    NSIndexPath *indexPath = params[@"indexPath"];
    UITableViewCell *cell = params[@"cell"];
    
    // 這里的TableViewCell的類型可以是自定義的多搀,我這邊偷懶就不自定義了。
    cell.textLabel.text = [NSString stringWithFormat:@"%@,%ld", title, (long)indexPath.row];
    return nil;
}

- (UIViewController *)Action_nativeFetchDetailViewController:(NSDictionary *)params
{
    // 因?yàn)閍ction是從屬于ModuleA的灾部,所以action直接可以使用ModuleA里的所有聲明
    DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
    viewController.valueLabel.text = params[@"key"];
    return viewController;
}

那么我們?cè)趺词褂肅TMediator進(jìn)行模塊間通信呢康铭?直接使用CTMediator,然后拼接scheme來進(jìn)行通信當(dāng)然也可以赌髓。但是感覺沒有那么友好从藤,使用過程中也容易出錯(cuò)。那么我們可以對(duì)CTMediator進(jìn)行一次封裝锁蠕,通過給CTMediator增加Category的方式夷野,來實(shí)現(xiàn)封裝好每個(gè)Target-Action提供的功能。這樣我們調(diào)用的時(shí)候荣倾,直接調(diào)用我們自己封裝的這一層Category的方法悯搔,傳遞進(jìn)來相關(guān)的參數(shù),就可以實(shí)現(xiàn)通信了舌仍。這個(gè)Category可以封裝成獨(dú)立的一個(gè)module妒貌,跟隨著業(yè)務(wù)進(jìn)行維護(hù)通危。
例如下面為#import "CTMediator+CTMediatorModuleAActions.h"的內(nèi)容:

NSString * const kCTMediatorTargetA = @"A";
NSString * const kCTMediatorActionNativeFetchDetailViewController = @"nativeFetchDetailViewController";

@implementation CTMediator (CTMediatorModuleAActions)
- (UIViewController *)CTMediator_viewControllerForDetail
{
    // 此處的performTarget方法為CTMediator的方法。
    UIViewController *viewController = [self performTarget:kCTMediatorTargetA
                                                    action:kCTMediatorActionNativeFetchDetailViewController
                                                    params:@{@"key":@"value"}
                                         shouldCacheTarget:NO
                                        ];
    if ([viewController isKindOfClass:[UIViewController class]]) {
        // view controller 交付出去之后灌曙,可以由外界選擇是push還是present
        return viewController;
    } else {
        // 這里處理異常場景菊碟,具體如何處理取決于產(chǎn)品
        return [[UIViewController alloc] init];
    }
}
@end

使用CTMediator進(jìn)行模塊間通信的流程圖如下:

使用CTMediator進(jìn)行模塊間通信

BeeHive方式進(jìn)行模塊間通信

一到多的通信:

系統(tǒng)事件的分發(fā):比如Application的相關(guān)事件,包括啟動(dòng)在刺、進(jìn)入前臺(tái)逆害、進(jìn)入后臺(tái)等事件。按照我們一般的方式蚣驼,如果我們需要在app進(jìn)入前臺(tái)的時(shí)候做一些事情魄幕,就得在AppDelegate中寫一些代碼。但是項(xiàng)目組件化后隙姿,如果在AppDelegate的代理方法中寫入各個(gè)module的代碼梅垄,耦合性也是比較強(qiáng)的厂捞。那么我們可以將這部分app生命周期的相關(guān)方法進(jìn)行下沉输玷,然后其他的模塊就可以直接獲取到app生命周期的回調(diào)了。整個(gè)過程如下:

  • 1靡馁、AppDelegate集成與BHAppDelegate欲鹏,那么App的生命周期都會(huì)被下層的BHAppDelegate做攔截;
  • 2臭墨、AppDelegate各個(gè)需要提供給其他模塊的方法封裝成protocol的形式來提供給外面赔嚎;
  • 3、在需要獲取到App生命周期的模塊中胧弛,通過BHModuleManager進(jìn)行注冊(cè)成為觀察者尤误,同時(shí)遵守protocol協(xié)議,實(shí)現(xiàn)協(xié)議方法结缚。BHModuleManager會(huì)綁定一個(gè)Context损晤,context中保存了App的一些全局的信息;
  • 4红竭、BHAppDelegate在對(duì)應(yīng)的事件發(fā)生的時(shí)候通知遵守協(xié)議的注冊(cè)者尤勋。

這樣的話,其他的module茵宪,想要在app的生命周期方法中做些事情最冰,只需要通過BHModuleManager注冊(cè)就可以了。而不需要直接和AppDelegate進(jìn)行耦合稀火。

點(diǎn)到點(diǎn)的通信:

上面介紹了BeeHive一對(duì)多的通信方式暖哨,下面我們介紹下一對(duì)一的通信方式:
一對(duì)一的通信方式是通過協(xié)議和類對(duì)象綁定的方式。通過注冊(cè)的方式將Class和protocol綁定在一起凰狞,也就是將Class和protocol放到Dictionay中以鍵值對(duì)的方式存起來篇裁,然后想要獲取到Class箕慧,只需要拿到protocol,然后到Dictionay中就能拿到對(duì)應(yīng)Class對(duì)象茴恰。Class對(duì)象可以執(zhí)行protocol中的方法颠焦。
注冊(cè)的方式分為兩種:一種是動(dòng)態(tài)的注冊(cè);一種為靜態(tài)注冊(cè)往枣。動(dòng)態(tài)注冊(cè)是在Class文件中使用宏聲明該類為模塊入口伐庭。靜態(tài)注冊(cè)是將Class和protocol寫入plist文件中,然后應(yīng)用啟動(dòng)的時(shí)候回去加載plist文件進(jìn)行注冊(cè)分冈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末圾另,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雕沉,更是在濱河造成了極大的恐慌集乔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坡椒,死亡現(xiàn)場離奇詭異扰路,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)倔叼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門汗唱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丈攒,你說我怎么就攤上這事哩罪。” “怎么了巡验?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵际插,是天一觀的道長。 經(jīng)常有香客問我显设,道長框弛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任敷硅,我火速辦了婚禮功咒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绞蹦。我一直安慰自己力奋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布幽七。 她就那樣靜靜地躺著景殷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猿挚,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天咐旧,我揣著相機(jī)與錄音,去河邊找鬼绩蜻。 笑死铣墨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的办绝。 我是一名探鬼主播伊约,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼孕蝉!你這毒婦竟也來了屡律?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤降淮,失蹤者是張志新(化名)和其女友劉穎超埋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佳鳖,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霍殴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腋颠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片繁成。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吓笙,死狀恐怖淑玫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情面睛,我是刑警寧澤絮蒿,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站叁鉴,受9級(jí)特大地震影響土涝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幌墓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一但壮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧常侣,春花似錦蜡饵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春焦辅,著一層夾襖步出監(jiān)牢的瞬間博杖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工筷登, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剃根,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓前方,卻偏偏與公主長得像跟继,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子镣丑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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