iOS组件化方案与实践:Target-Action

目前项目组件化已经告一段落,我把总结的相关文章列罗出来
创建cocoapod私有库详细步骤(基础组件组件化)
iOS组件化方案与实践:Target-Action
iOS组件化解决图片显示问题
xib文件如何组件化(cocoapod私有库)?
适合小白的iOS项目组件化完整详细流程,每步都有demo
pod trunk push使用
iOS项目组件化遇到的问题及解决(100%遇得到)
Cocoapods 更新索引库或者指定第三方

概述

根据CTMediator写了个准备实施组件化的组件化前demo,以及完成组件化demo

我把对目前项目从零到组件化完成过程中遇到的问题总结在这里

如果你准备组件化的话,肯定遇得到(╯﹏╰)

一、demo结构

该方案基于Mediator和Target-Action模式组件化,通过运行时完成调用。简单来说:Mediator维护着若干个category,一个category对应一个target,一个target可以包含多个action。
可以这么理解:一个A业务组件包含一个category组件,这个category组件中有个Mediator的category,这个category中有一个target,这个target属于对应的A业务组件,target中会有若干接口方法,用来其他业务组件通过这个category获取到A业务组件中的业务。
所有组件都通过组件自带的Target-Action来响应,也就是说,模块与模块之间的接口被固化在了Target-Action这一层。
对CTMediator的详细解读可参考该文章

接下来介绍下本文demo,共包含两个模块:TAPersonInfo和TAPersonPrefrence,我在这里强制认为这是两个业务组件(别较真哈),这两个组件中有业务交互。
首页:


image.png

点击个人详情进入第一个业务组件TAPersonInfo:

image.png

点击开始打分按钮进入第二个业务组件TAPersonPrefrence:

image.png

点击喜欢或者烦之后返回第一个模块,并把选择的结果显示出来。

image.png

组件化之前和组件化之后的各个pod以及主工程demo我在下面给出,大家自行下载:
组件化之前主工程
TAPersonInfo业务地址
TAPersonInfo业务category地址
TAPersonPrefrence业务地址
TAPersonPrefrence业务category地址
存放索引文件(podspec)库
组件化完成后的主工程

下面介绍如何根据CTMediator实现本文demo。

1、主界面只有一个“个人详情”按钮,点击按钮进入个人详情模块TAPersonInfo。
通常实现方式为:
先在主页引入头文件

#import "WGPersonInfoViewController.h"

然后

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

在个人页面进入个人偏好页面的方式与上述相同。
这么做没有什么不对,但当项目越来越大,从主页跳转的页面越来越多时,导入的头文件也会越来越多,进而导致多文件之间的相互依赖。在做组件化时不可能为了拆分组件而把头文件也引入进来,为做组件化造成困难。
为了解除业务组件之间的耦合,就要换种方式来实现。

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

3、个人详情TAPersonInfo默认是一个单独模块,组件化时TAPersonInfo就是一个单独project,为了方便其他模块调用,我们需要先给TAPersonInfo建立一个对外提供服务的接口,即wgPersonInfoCatogeryKit分类。
我们从主页跳到个人详情页业务场景是:进入到个人详情页时需要传给此页面名字和年龄两个值,并在该页面显示。
实现如下:

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

主页面调用如下:

#import "CTMediator+TAPersonInfo.h"

......

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

主页通过catogery入口,把需要传递的参数放到字典之中,然后调用CTMediator开源库performTarget: action:params: shouldCacheTarget方法,传递target(WGPersonInfoViewController)和action(PersonInfoViewController)名称以及参数字典,在.m文件中通过runtime让target执行action方法,完成具体场景功能。

image.png
image.png

细心地话,会发现tatget和action与传递过来的名称不一样,在前面多了一个前缀,这是因为在CTMediator中:

image.png

在target中可以引入WGPersonInfoViewController.h头文件是因为他们在一个模块中。

该target中的action返回需要的viewController,在主页面拿到viewController后就可以push到对应页面。

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

4、从TAPersonInfo个人详情页进入第二个模块TAPersonPrefrence实现方式同上。

5、到此就完成了该demo的全部内容。

二、拆分业务,实现组件化

根据上述对项目结构的讲解,我们首先需要拆分出两个组件:TAPersonInfo和TAPersonPrefrence,同时为了组件之间的相互调用,还需要为这两个组件各建一个category组件,最后总共需要wgPersonInfoKit、wgPersonInfoCatogeryKit、wgPersonPrefenceKit、wgPersonPrefrenceCatogeryKit四个组件。

1、为了方便管理,我在github上新建一个organization,里面专门存放这次组件化的各个组件。

image.png

2、建立pod步骤在我的这篇文章中有非常详细的讲解,我的四个组件也是按照其中的步骤一步一步建立的。
这里我简单说下步骤和需要注意的地方:

. 新建一个repo索引文件库(用来存放xxx.podspec,包括远程和本地)。
. 新建wgPersonInfoKit 组件 (本地和远程)
. 新建wgPersonInfoCatogeryKit组件 (本地和远程)
. 新建wgPersonPrefenceKit组件(本地和远程)
. 新建wgPersonPrefrenceCatogeryKit 组件(本地和远程)
. 主工程pod 这四个组件,删除项目中的原本代码,运行即可。

注意:

1、依赖
新建wgPersonInfoCatogeryKit、wgPersonPrefrenceCatogeryKit、wgPersonPrefrenceCatogeryKit时和组件化基础组件不一样的地方在基础组件组件化时,代码中没有依赖其他第三方,所以在podspec文件中不需要有其他的第三方依赖,下图是我在基础组件组件化中生成的podspec文件,可看到里面没有第三方依赖。

image.png

在本文的这四个组件,wgPersonInfoCatogeryKit、wgPersonPrefrenceCatogeryKit依赖CTMediator开源库;wgPersonInfoKit依赖建好的组件wgPersonPrefrenceCatogeryKit;所以在修改podspec文件时,在文件最后需要加上依赖。我在下面给出这三个组件的podspec内容:
wgPersonInfoCatogeryKit和wgPersonPrefrenceCatogeryKit的podspec依赖部分:

image.png

wgPersonInfoKit的podspec依赖部分:

image.png

所以在组件化上传podspec文件时要把wgPersonPrefrenceCatogeryKit放在wgPersonInfoKit前面,不然验证不会通过。

2、验证:
把组件podspec索引文件上传索引库时会有验证步骤,在验证wgPersonInfoKit.podspec时可能会报如下错误:

image.png

报这个错的原因是校验podspec文件时默认只会到官方specs库(https://github.com/CocoaPods/Specs.git)去校验,这时候就需要同时指定自己创建的远程索引库地址库校验。

解决办法:

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

原因是默认会从master的索引库查找,master里并没有该组件。
解决办法是需要指定组件远程索引库地址:

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

完整的Podfile如图:

image.png

这时候cd到主项目根目录后,执行pod install后会pod进入五个

image.png

这是因为组件中存在依赖关系,想查看这种依赖关系的话,也很简单,在主工程目录中,和Podfile在同一层级有一个

image.png

打开可看到依赖关系:

image.png

到此,主项目目录为:

image.png

到此,工程中已经没有了TAPersonInfo和TAPersonPrefrence两个模块,完成组件化。运行结果和没有组件化之前效果一样。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容