iOS組件化方案與實踐:Target-Action

目前項目組件化已經(jīng)告一段落,我把總結(jié)的相關(guān)文章列羅出來
創(chuàng)建cocoapod私有庫詳細(xì)步驟(基礎(chǔ)組件組件化)
iOS組件化方案與實踐:Target-Action
iOS組件化解決圖片顯示問題
xib文件如何組件化(cocoapod私有庫)?
適合小白的iOS項目組件化完整詳細(xì)流程,每步都有demo
pod trunk push使用
iOS項目組件化遇到的問題及解決(100%遇得到)
Cocoapods 更新索引庫或者指定第三方

概述

根據(jù)CTMediator寫了個準(zhǔn)備實施組件化的組件化前demo,以及完成組件化demo

我把對目前項目從零到組件化完成過程中遇到的問題總結(jié)在這里

如果你準(zhǔn)備組件化的話,肯定遇得到(╯﹏╰)

一、demo結(jié)構(gòu)

該方案基于Mediator和Target-Action模式組件化,通過運行時完成調(diào)用。簡單來說:Mediator維護(hù)著若干個category,一個category對應(yīng)一個target,一個target可以包含多個action。
可以這么理解:一個A業(yè)務(wù)組件包含一個category組件,這個category組件中有個Mediator的category,這個category中有一個target,這個target屬于對應(yīng)的A業(yè)務(wù)組件,target中會有若干接口方法,用來其他業(yè)務(wù)組件通過這個category獲取到A業(yè)務(wù)組件中的業(yè)務(wù)。
所有組件都通過組件自帶的Target-Action來響應(yīng),也就是說,模塊與模塊之間的接口被固化在了Target-Action這一層。
對CTMediator的詳細(xì)解讀可參考該文章。

接下來介紹下本文demo,共包含兩個模塊:TAPersonInfo和TAPersonPrefrence,我在這里強制認(rèn)為這是兩個業(yè)務(wù)組件(別較真哈),這兩個組件中有業(yè)務(wù)交互。
首頁:


image.png

點擊個人詳情進(jìn)入第一個業(yè)務(wù)組件TAPersonInfo:

image.png

點擊開始打分按鈕進(jìn)入第二個業(yè)務(wù)組件TAPersonPrefrence:

image.png

點擊喜歡或者煩之后返回第一個模塊,并把選擇的結(jié)果顯示出來。

image.png

組件化之前和組件化之后的各個pod以及主工程demo我在下面給出,大家自行下載:
組件化之前主工程
TAPersonInfo業(yè)務(wù)地址
TAPersonInfo業(yè)務(wù)category地址
TAPersonPrefrence業(yè)務(wù)地址
TAPersonPrefrence業(yè)務(wù)category地址
存放索引文件(podspec)庫
組件化完成后的主工程

下面介紹如何根據(jù)CTMediator實現(xiàn)本文demo。

1、主界面只有一個“個人詳情”按鈕,點擊按鈕進(jìn)入個人詳情模塊TAPersonInfo。
通常實現(xiàn)方式為:
先在主頁引入頭文件

#import "WGPersonInfoViewController.h"

然后

    WGPersonInfoViewController *perCon = [[WGPersonInfoViewController alloc] init];
    [self.navigationController pushViewController:perCon animated:YES];

在個人頁面進(jìn)入個人偏好頁面的方式與上述相同。
這么做沒有什么不對,但當(dāng)項目越來越大,從主頁跳轉(zhuǎn)的頁面越來越多時,導(dǎo)入的頭文件也會越來越多,進(jìn)而導(dǎo)致多文件之間的相互依賴。在做組件化時不可能為了拆分組件而把頭文件也引入進(jìn)來,為做組件化造成困難。
為了解除業(yè)務(wù)組件之間的耦合,就要換種方式來實現(xiàn)。

2、Podfile中 pod 'CTMediator 把CTMediator引入工程中。

3、個人詳情TAPersonInfo默認(rèn)是一個單獨模塊,組件化時TAPersonInfo就是一個單獨project,為了方便其他模塊調(diào)用,我們需要先給TAPersonInfo建立一個對外提供服務(wù)的接口,即wgPersonInfoCatogeryKit分類。
我們從主頁跳到個人詳情頁業(yè)務(wù)場景是:進(jìn)入到個人詳情頁時需要傳給此頁面名字和年齡兩個值,并在該頁面顯示。
實現(xiàn)如下:

image.png
.h文件中

#import <CTMediator/CTMediator.h>

@interface CTMediator (TAPersonInfo)

- (UIViewController *)personInfoWithName:(NSString *)name age:(NSInteger)age;

@end
.m文件中

#import "CTMediator+TAPersonInfo.h"

@implementation CTMediator (TAPersonInfo)

- (UIViewController *)personInfoWithName:(NSString *)name age:(NSInteger)age{
    
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
    [dic setValue:name forKey:@"name"];
    [dic setValue:@(age) forKey:@"age"];
    
    return [self performTarget:@"WGPersonInfoViewController" action:@"PersonInfoViewController" params:dic shouldCacheTarget:NO];
}

@end

主頁面調(diào)用如下:

#import "CTMediator+TAPersonInfo.h"

......

- (void)btnClicked{
    UIViewController *con = [[CTMediator sharedInstance] personInfoWithName:@"寒江" age:18];
    [self.navigationController pushViewController:con animated:YES];
}

主頁通過catogery入口,把需要傳遞的參數(shù)放到字典之中,然后調(diào)用CTMediator開源庫performTarget: action:params: shouldCacheTarget方法,傳遞target(WGPersonInfoViewController)和action(PersonInfoViewController)名稱以及參數(shù)字典,在.m文件中通過runtime讓target執(zhí)行action方法,完成具體場景功能。

image.png
image.png

細(xì)心地話,會發(fā)現(xiàn)tatget和action與傳遞過來的名稱不一樣,在前面多了一個前綴,這是因為在CTMediator中:

image.png

在target中可以引入WGPersonInfoViewController.h頭文件是因為他們在一個模塊中。

該target中的action返回需要的viewController,在主頁面拿到viewController后就可以push到對應(yīng)頁面。

- (void)btnClicked{
    UIViewController *con = [[CTMediator sharedInstance] personInfoWithName:@"寒江" age:18];
    [self.navigationController pushViewController:con animated:YES];
}

4、從TAPersonInfo個人詳情頁進(jìn)入第二個模塊TAPersonPrefrence實現(xiàn)方式同上。

5、到此就完成了該demo的全部內(nèi)容。

二、拆分業(yè)務(wù),實現(xiàn)組件化

根據(jù)上述對項目結(jié)構(gòu)的講解,我們首先需要拆分出兩個組件:TAPersonInfo和TAPersonPrefrence,同時為了組件之間的相互調(diào)用,還需要為這兩個組件各建一個category組件,最后總共需要wgPersonInfoKit、wgPersonInfoCatogeryKit、wgPersonPrefenceKit、wgPersonPrefrenceCatogeryKit四個組件。

1、為了方便管理,我在github上新建一個organization,里面專門存放這次組件化的各個組件。

image.png

2、建立pod步驟在我的這篇文章中有非常詳細(xì)的講解,我的四個組件也是按照其中的步驟一步一步建立的。
這里我簡單說下步驟和需要注意的地方:

. 新建一個repo索引文件庫(用來存放xxx.podspec,包括遠(yuǎn)程和本地)。
. 新建wgPersonInfoKit 組件 (本地和遠(yuǎn)程)
. 新建wgPersonInfoCatogeryKit組件 (本地和遠(yuǎn)程)
. 新建wgPersonPrefenceKit組件(本地和遠(yuǎn)程)
. 新建wgPersonPrefrenceCatogeryKit 組件(本地和遠(yuǎn)程)
. 主工程pod 這四個組件,刪除項目中的原本代碼,運行即可。

注意:

1、依賴
新建wgPersonInfoCatogeryKit、wgPersonPrefrenceCatogeryKit、wgPersonPrefrenceCatogeryKit時和組件化基礎(chǔ)組件不一樣的地方在基礎(chǔ)組件組件化時,代碼中沒有依賴其他第三方,所以在podspec文件中不需要有其他的第三方依賴,下圖是我在基礎(chǔ)組件組件化中生成的podspec文件,可看到里面沒有第三方依賴。

image.png

在本文的這四個組件,wgPersonInfoCatogeryKit、wgPersonPrefrenceCatogeryKit依賴CTMediator開源庫;wgPersonInfoKit依賴建好的組件wgPersonPrefrenceCatogeryKit;所以在修改podspec文件時,在文件最后需要加上依賴。我在下面給出這三個組件的podspec內(nèi)容:
wgPersonInfoCatogeryKit和wgPersonPrefrenceCatogeryKit的podspec依賴部分:

image.png

wgPersonInfoKit的podspec依賴部分:

image.png

所以在組件化上傳podspec文件時要把wgPersonPrefrenceCatogeryKit放在wgPersonInfoKit前面,不然驗證不會通過。

2、驗證:
把組件podspec索引文件上傳索引庫時會有驗證步驟,在驗證wgPersonInfoKit.podspec時可能會報如下錯誤:

image.png

報這個錯的原因是校驗podspec文件時默認(rèn)只會到官方specs庫(https://github.com/CocoaPods/Specs.git)去校驗,這時候就需要同時指定自己創(chuàng)建的遠(yuǎn)程索引庫地址庫校驗。

解決辦法:

pod spec lint wgPersonInfoKit.podspec --verbose --allow-warnings --sources='[https://github.com/CocoaPods/Specs.git,https://github.com/wgModularization/WGModulSpecs.git](https://github.com/CocoaPods/Specs.git,https://github.com/wgModularization/WGModulSpecs.git)'

如圖,驗證通過。


image.png

3、pod四個組件

在主工程Podfile文件中:

pod 'wgPersonInfoKit'
pod 'wgPersonInfoCatogeryKit'
pod 'wgPersonPrefenceKit'
pod 'wgPersonPrefrenceCatogeryKit'

可能會報如下錯誤

image.png

原因是默認(rèn)會從master的索引庫查找,master里并沒有該組件。
解決辦法是需要指定組件遠(yuǎn)程索引庫地址:

source 'https://github.com/wgModularization/WGModulSpecs.git'
source 'https://github.com/CocoaPods/Specs.git'

完整的Podfile如圖:

image.png

這時候cd到主項目根目錄后,執(zhí)行pod install后會pod進(jìn)入五個

image.png

這是因為組件中存在依賴關(guān)系,想查看這種依賴關(guān)系的話,也很簡單,在主工程目錄中,和Podfile在同一層級有一個

image.png

打開可看到依賴關(guān)系:

image.png

到此,主項目目錄為:

image.png

到此,工程中已經(jīng)沒有了TAPersonInfo和TAPersonPrefrence兩個模塊,完成組件化。運行結(jié)果和沒有組件化之前效果一樣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容