iOS组件化(中篇)-拆分业务组件

        在上一篇中对基础组件进行了拆分,接下来会拆分业务组件。业务组件最简单的理解(比如,有3个tabbar专题、作者、商城三个模块,就可以理解成3个业务组件)。功能组件也很好理解,比如我们项目中用到的轮播器、播放器、图片浏览器等都可以单独抽出功能组件。

在拆分业务组件之前,需要了解组件间通信的概念?笔者这里要说的是业务组件间的通信。比如专题组件A、作者组件B、点击专题A组件中cell的作者头像图标跳转到B组件中“作者详情”的界面。这就是简单的组件间通信,假如不允许直接import引入依赖,该怎么进行跳转?

关于组件间的通信的几种方式以及利弊《这篇文章》已经说的很详细了。笔者采用的就是文章中提出的基于Mediator模式和Target-Action模式组件化方案,中间采用了runtime来完成调用。基于Mediator模式和Target-Action模式组件化方案如下图所示,会用到开源库CTMediator

由上图可见,专题A组件和作者B组件都对外提供了一个Target的API类(Target_A和Target_B),  同时需要为A组件和B组件创建对应的A_category组件和B_category组件(Category组件依赖CTMediator库),Category组件需要提供A_CTM分类、和B_CTM分类,A_CTM分类、和B_CTM分类里的方法对应了这个Target下所有可能的调用场景,这样调用者在包含mediator的时候,自动获得了所有可用的Target-action,无论是调用还是参数传递,都非常方便。为什么是Category而不是其他 。

以下内容摘自《iOS应用架构谈 组件化方案》


1. category本身就是一种组合模式,根据不同的分类提供不同的方法,此时每一个组件就是一个分类,因此把每个组件可以支持的调用用category封装是很合理的。

2. 在category的方法中可以做到参数的验证,在架构中对于保证参数安全是很有必要的。当参数不对时,category就提供了补救的入口。

3. category可以很轻松地做请求转发,如果不采用category,请求转发逻辑就非常难做了。

4. category统一了所有的组件间调用入口,因此无论是在调试还是源码阅读上,都为工程师提供了极大的方便。

5. 由于category统一了所有的调用入口,使得在跨模块调用时,对于param的hardcode在整个App中的作用域仅存在于category中,在这种场景下的hardcode就已经变成和调用宏或者调用声明没有任何区别了,因此是可以接受的。


接下来一步步实现业务组件拆分

1. 首先远程和本地创建专题组件A和作者组件B。

2. 通过pod lib create在本地创建相应的代码模版.同样把special、author文件夹拖入到对应的FFSpecialKit、FFAuthorKit的classes路径下面。


3. 修改.podspec索引文文件和Podfile文件后执行pod install,修改ReactiveCocoa和Result的UseLegacySwiftLanguage Version 设置成YES。

修改podspec索引文件
添加依赖
修改podfile

4. 编译此时会报错各种文件找不到。新建一个FFSpecialKit.h的文件专门引入头文件。然后将原来#import “public.h” 替换成#import “FFSpecialKit.h"

5.  再次编译会报下面的文件找不到,然后先将“FFAuthorDetailController”,“FFAuthorListReformer”这几个文件相关的代码注释了.再次编译会报下面的错误,然后同样将相关代码注释掉编译就OK了。

6.  FFSpecialKit组件编译通过之后,按照同样的方式处理FFAuthorKit组件并使其编译通过.接下来为组件FFSpecialKit 和FFAuthorKit创建对应的Target_Special和Target_Author文件(创建完之后执行一次pod insall)



```

#import"Target_Author.h"

#import"FFAuthorDetailController.h"

#import"FFAuthorListReformer.h"

#import"AuthorAPIRequest.h"

@implementationTarget_Author

- (UIViewController*)Action_authorDetailViewController:(NSDictionary*)params {

return[[FFAuthorDetailControlleralloc]init];

}

- (NSDictionary*)Action_authorReformerWithOriginData:(NSDictionary*)params {

FFAuthorListReformer*reformer = [[FFAuthorListReformeralloc]init];

returnparams ? [reformerreformData:params] :nil;

}

- (NSDictionary *)Action_authorReformer:(NSDictionary*)params {

return[[FFAuthorListReformeralloc]init];

}

- (APIRequest*)Action_authorAPIRequest:(NSDictionary*)params {

return[[AuthorAPIRequestalloc]init];

}

@end

```

```

#import

#import"FFSpecialKit.h"

@interfaceTarget_Special :NSObject

- (UIViewController*)Action_specialDetailViewController:(NSDictionary*)params;

- (NSDictionary*)Action_specialReformerWithOriginData:(NSDictionary*)params;

- (NSDictionary *)Action_specialReformer:(NSDictionary*)params;

- (APIRequest*)Action_specialAPIRequest:(NSDictionary*)params;

@end

```


```

#import"Target_Special.h"

#import"FFSpecialDetailController.h"

#import"FFSpecialListReformer.h"

#import"SpecialAPIRequest.h"

@implementationTarget_Special

- (UIViewController*)Action_specialDetailViewController:(NSDictionary*)params {

return[[FFSpecialDetailControlleralloc]init];

}

- (NSDictionary*)Action_specialReformerWithOriginData:(NSDictionary*)params {

FFSpecialListReformer*reformer = [[FFSpecialListReformeralloc]init];

returnparams ? [reformerreformData:params] :nil;

}

- (NSDictionary *)Action_specialReformer:(NSDictionary*)params {

return[[FFSpecialListReformeralloc]init];

}

- (APIRequest*)Action_specialAPIRequest:(NSDictionary*)params {

return[[SpecialAPIRequestalloc]init];

}

@end

```

7. 接下来就该创建对应的FFSpecialKit_Category 和FFAuthorKit_Category组件了。

8. 修改FFSpecialKit_Category对应的podspec文件和Podfile文件.

9. 创建对应的CTMediator+Special分类(创建分类时的存储路径需要注意一下)

```

#import <UIKit/UIKit.h>

#import <CTMediator/CTMediator.h>

#import <FFAPIsKit/APIRequest.h>

#import <FFAPIsKit/FFReformProtocol.h>

@interfaceCTMediator (Special)

- (UIViewController*)specialDetailController;

- (NSDictionary*)specialReformerWithOriginData:(NSDictionary*)data;

- (NSDictionary *)specialReformer;

- (APIRequest*)specialAPIRequest;

@end

```

```

#import"CTMediator+Special.h"

@implementationCTMediator (Special)

- (UIViewController*)specialDetailController {

return[selfperformTarget:@"Special"action:@"specialDetailViewController"params:nilshouldCacheTarget:NO];

}

- (NSDictionary*)specialReformerWithOriginData:(NSDictionary*)data {

return[selfperformTarget:@"Special"action:@"specialReformerWithOriginData"params:datashouldCacheTarget:NO];

}

- (NSDictionary *)specialReformer {

return[selfperformTarget:@"Special"action:@"specialReformer"params:nilshouldCacheTarget:NO];

}

- (APIRequest*)specialAPIRequest {

return[selfperformTarget:@"Special"action:@"specialAPIRequest"params:nilshouldCacheTarget:NO];

}

@end

```

10. 编译通过,按照同样的方式修改FFAuhtorKit_Category的podspec文件和Podfile文件,创建对应的CTMediator+Ahthor分类(创建完之后记得先pod install一下);然后编写分类分类内容如下.

```

#import <UIKit/UIKit.h>

#import <CTMediator/CTMediator.h>

#import <FFAPIsKit/APIRequest.h>

@interfaceCTMediator (Author)

- (UIViewController*)authorDetailViewController;

- (NSDictionary*)authorReformerWithOriginData:(NSDictionary*)data;

- (NSDictionary *)authorReformer;

- (APIRequest*)authorAPIRequest;

@end

```

```

#import"CTMediator+Author.h"

@implementationCTMediator (Author)

- (UIViewController*)authorDetailViewController {

return[selfperformTarget:@"Author"action:@"authorDetailViewController"params:nilshouldCacheTarget:NO];

}

- (NSDictionary*)authorReformerWithOriginData:(NSDictionary*)data {

return[selfperformTarget:@"Author"action:@"authorReformerWithOriginData"params:datashouldCacheTarget:NO];

}

- (NSDictionary *)authorReformer {

return[selfperformTarget:@"Author"action:@"authorReformer"params:nilshouldCacheTarget:NO];

}

- (APIRequest*)authorAPIRequest {

return[selfperformTarget:@"Author"action:@"authorAPIRequest"params:nilshouldCacheTarget:NO];

}

@end

```

11. 到此都创建完毕之后就可以提交FFSpecialKit_Category和FFAuhtorKit_Category组件了.还是通过下面步骤提交组件.


-  git add .

- git commit -m “xxx"

- git remote add origin 远程代码仓库地址

- git push origin master

- git tag 版本号 (注:这里的版本号必须和podspec里写的版本号一致)

- git push --tags


12. 通过pod spec lintFFSpecialKit.podspec - -verbose - -allow-warnings 验证索引文件的有效性,这里需要说明一些细节问题,验证时会报下面的错误.

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

解决如下:pod spec lint FFSpecialKit.podspec --verbose --allow-warnings --sources='https://github.com/FFComponent/FFSpecs.git,https://github.com/CocoaPods/Specs.git

继续验证报下面的错误

解决办法:在终端输入**`echo "2.3" > .swift-version` **

继续通过上面的命令验证,报下面的错误.

解决办法:

第一步:回到FFSpecialKit.h 导入到文件

第二步: 将原来**#import “FFSpecialListReformerKeys.h"** 的地方注释掉,替换成**#import“FFSpecialKit.h"**

第三步:编译一下组件,编译通过后,需要重新修改一下**FFSpecialKit.podspec**文件中的版本号,重新提交,重新打tag(上一次tag是1,这次tag累加为2) (因为代码做了修改,所以需要重新提交)

第四步:提交并打好tag后,再次进行验证就ok了.

第五步:最后,通过pod repo push ...提交索引文件就完成了。

按照上面的方式提交组件FFAuthorKit,都提交成功之后回到项目FlowerField_Component,然后修改Podfile文件,然后执行pod install.

安装完成之后,编译运行.

中篇到这里就结束了,最后需要说明一下,因为点击专题cell时跳转过去的详情界面,我特意用了XIB。这里点击cell进行跳转操作时会奔溃,具体如何去处理组件化过程中XIB以及一些图片资源,我将在下一篇中详细说明。再次感谢您的阅读。欢迎大家评论交流。

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

推荐阅读更多精彩内容