组件化初探

为什么需要组件化

  • 模块间解耦
  • 模块重用
  • 提高团队协作开发效率
  • 便于单元测试

哪些项目不需要组件化

  • 项目较小,模块之间交互简单、耦合少
  • 模块没有被多狗狗币个外部模块引用,只是一个简单的小模块
  • 模块不需要重用,代码也很少被修改
  • 团队规模小源码资本

组件化分层设计

iOS 组件化方案总结

底层组件通常包括底层类库、分类、宏定义文件等

注意:组件化分层实际就是通过接口隔离实现分层之间的依赖关系,而且只能上层spring是什么意思中文翻译对下层依赖项⽬公共代码资源下沉,横向的依赖也最好下沉

cocoapods 创建私有库

私有库创建流程如下:

iOS 组件化方案总结

写个 Demo 说明一下具体流程运营

1、在终端上移动到你想创建pod库工程的路径,并执行运营计划书pod库的创建。命令如下:

plz@plzdehttps安全问题MacSpringBook-Pro:~ better$ cd desktop
plz@plzdeMacBook-Pro:desktop better$ pod lib create PrivateHelloWorld

iOS 组件化方案总结

Go车之后,终端会询问运营商几个问题

# 选择编程语言
What language do you want to use?? [ Swift / ObjC ]
> Objc
# 在你的项目中是否创建一个demo工程,为了方便测试,我选择了Yes
Would you like to includ源码网站e 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 ]
&g公积金t; NO
# 类前缀名
What is your classpring是什么意思s prefix?
> HG

iOS 组件化方案总结

Pod私有库创建成功。一般来说创建成功会自动打开项目

2、安装CocoaPods项目找到刚才创建的PrivateHelloWorld文件夹,点击入去,里面的目录如下

iOS 组件化方案总结

3、添源码超市加你要添加代码文件(复制粘贴)

iOS 组件化方案总结

我这里放了Prinhttps安全问题tHelloWorld文运营商pod instal源码交易网站源码l一下

# 移到Example目录下
Bettespring是什么意思rdeMacBook-Pro:desktop better$ cd /Users/better/Desktop/PrivateHelloWorld/Example
# 安装CocoaPods项目
BetterdeMacBook-Pro运营是做什么的:Example b运营管理etter$ pod install --no-repo-update

iOS 组件化方案总结

先进去Example文件夹点击后缀为xcworkspace的文件打开项目,运行下是否成功。

4、编辑CocoaPods的配置文件(后缀名为pod运营专员主要做什么spec)

打开PrintHelloWorld文件夹就可以看到

可以有很多种编辑方式编辑这个文件,如Xcode、文本编辑器、Subli源码之家me Text系列、Atom
我是用文本编辑器打开,难看是难看点,但胜在够方便

iOS 组件化方案总结

s.version我习惯是0.0.1开始
s.su运营是做什么的工作内容是什么mmary需要改改,不然待会提交会报错
s.homepage这里随便写个网站都行,建议写项目的首页,但一定要改,不然默认的会报错https域名,因为没有默认的网址宫崎骏

s.sohttps域名urce需要填一个git地址的私有库,gith运营ub收费的,我选择的gitLab

iOS 组件化方案总结

复制私有库地址宫颈癌,在.podspec文件内的s.source替换地址

配置完成了

再次移到我们的Example文件运营是做什么的工作内容是什么,pod更新一下

BetterdeMacBoospringfieldk-Pro:Example better$ pod update --no-repo-update

打开项目,看看是否成功了

5、添加PrintHelloWorld,运行测试打开项目,在BYViewController.m里面导入PrintHelloWorld.h文件

iOS 组件化方案总结

6、验证pod配置文件为了保证项目正确性,pod文件配置没问题,在提运营商交之前,工作总结我们需要验证一下

用终端移到我们的项目路径

BetterdeMacBook-Pro:~ better$ cd /Users/宫颈癌better运营计划书/Desktop/PriSpringvateHelloWorld

到这里,我们已经完成源码导入、验证项目是否能运行、pod配置文件本地验证了

7、项目发布,tag 0.0.1终端移到该功夫战警项目spring festival文件下执行git的相关命令

# 添加远程地址,即上面创建码云项目的地址
BetterdeMacBook-Pro:PrivateHellspringfieldoWorldspring是什么意思中文翻译 better$ git remote add origin https://gitee.com/Better_Y/PrintHelloWorld.git
# 添加文件
Bette源码超市rdeMacBook-Progoogle:PrivateHelloWorld better$ git add .
# 提交本地,并写描述
BetterdeMacBook-Pro:PrivateHelloWorld bet运营是做什么的ter$ git commit -a -m "第一次提交 版本为0.0.1"
# --allow-unrelated-histories
# git pull or源码之家igin maste会失运营商败 ,提示:fatal: refusing to merge unrelated histories
# 原因是远程仓库origin上的分支master和本地分支master被Git认为是不同的仓库,Spring所以不能直接合并,需要添加 --allow-unrelated-histories
BetterdeMacBook-Pro:PrivateHelloWorld better$ git pull origin master --allow-unrelated-histories
# 推送到码云的PrintHelloWolrd项目的master分支上
Betterd功夫战警eMacBook-Pro:PrivateHelloWorld better$ gitspring框架 push origin master
# 提交版本号
BetterdeMacBook-Pro:Prihttps安全问题vateHelloWorld better$ git tag 0.0.1
# push到远程分支
BetterdeMacBook-Pro:Pr源码编辑器编程猫下载ivateHellospringWorld better$ git push origi源码n 0.0.1

8、创建Sepc管理库 创建步骤跟上面码springcloud云创建的git私有库同理

在终端执行Specs创建命令

BetterdeMacBook-PGoro:PrivateHelloWorld better$ pod repo add PrintSgooglepe功夫战警cs https://gitlab.com/peiliuzhen/testspecs.git

现在,我们可以直接发布了

# PrintSp源码ecs是刚才上面添加的管理库名字
# PrivateHelloWorld.podspec是PrintHelloWorld项目里面后缀为podspec的文件名
BetterdeMacBook-Pro:PrivateHelloWorld better$ pod rep运营是做什么的工作内容是什么o push PrintSpecs PrivateHelloWorld.podspec

发布成功后,我们可以去码云看看Privatespringfestival手抄报Specs的git项目有没有提交成功

iOS 组件化方案总结

到这里,我们的私有库发布已经全部完成了

9、检验私有库发布

新建privateDemo项目,创建Podfile文件并安装
Podfile代码如下

platform :ios,'8.0'
target 'privateDemo' do
pod 'PrintHelloWorld',:git =spring festival> 'https://gitlab.com/peiliuzhen/privatehelloworld.git'
end

打开终端并执行pod安装指令:

BetterdeMacBook-Pro:功夫战警~ better$ cd /Userhttps域名s/better/Desktop/privateDemo
BetterdeMacBook-Pro:privateDemo better$ pod install --n运营及偿债能力评级到安徽福友企业咨询o-repo-update

我们打开PrivateDemo项目目录看看

iOS 组件化方案总结

到这里,验证我们的私有库发布源码网站就完满结束了!!

组件化基本操作

抽取解封装

使用spring festival一个常见的列表页举例说明:

iOS 组件化方案总结

cell的封装抽离:

iOS 组件化方案总结

组件化模块处理

模块耦合

iOS 组件化方案总结

模块解耦

iOS 组件化方案总结

组件通信

模块之间通信

iOS 组件化方案总结

开源组件化框架推荐(MJRouter、CTMe狗狗币diator、BeeHive)

目前主流springcloud的组件化方式有三种

  • URL路由

  • target-action

  • protocol匹配

下面介绍一下三种方式对应的代表性框架

MJRouter(URL路由)

iOS常用路由工具一般都是使用URL匹配,或者根据约定的命名使用runtime方法进行动态调用。

这种实现方式优点是实现简单,缺点是需要维护字符串表,或者根据依赖命名约定无法在编译时暴露问题,运行时才发现错误。

URL 路由方式典型代表框架是蘑菇街开源的MGJRouter,还有JLRoutes,HHRouter等

MGJRouter实运营管理现分析:

  1. App 启动时实例化各组件模块或者使用class注册,然后组件向ModuleManager注册Url
  2. 当组件A需要调用组件B时,向ModuleManager传递URL,参数可以拼接在URL后面或者放在字典spring里传递,类似 openURspring框架L。然后由ModuleManager负责调度https域名组件B,最后完成目标

注册及调用代码如下:

// 1、注册某个URL[M工作总结GJGoRouter registerURLPattern:@"mgj://foo/bar" toHandler:^(NSDicspring是什么意思tionary *routerParameters) {
NSLog(@"routerParameterUserInfo:%@", routerParameters[MGJRouterParameter源码编辑器编程猫下载UserInfo]);
}];
//2、调用路由[MGJRouter openURL:@"mgj:功夫战警//foo/bar"]宫崎骏;
[MGJRouter registerURLPattern:@"mgj://category/travel" toHandler:^(NSDictspringcloudionary *routerParameters) {
NSLog(@"routerParameters[M源码编辑器GJRouterParameterUserInfo]:HTTPS%运营及偿债能力评级到安徽福友企业咨询@", routerParameters[MGJRouterParameterUserInfo]);
// @{@"user_id": @1900}
}];
[MGJRouter openURL:@"mgj://category/t宫崎骏ravel" withUserInfo:@{@"user_id运营证哪里考": @1spring900} completion:nil];

USpringRL 路由的优点

  • 具有很高的动态性,适合经常开展运营活动的app,例源码分享网如蘑菇街自身属于电商行业

  • 方便统一管理多平台的路由规则

  • 易于适配 URL Scheme

URl 路由的缺点

  • 传参方式有限,并且无法利用编译器进行参数类型检查,因此所有枸杞的参数都是通过字符串转换而来

  • 只适用于界面模块,不适用于通springfield用模块

  • 参数的狗狗币格式不明确,是个灵活的 dictionary,也需要有个地方可以查参数格式。

  • 不支持storyboard

  • 依赖于字符串硬编码,难以管理,蘑菇街做了个后台专门管理。

  • 无法保证所使用的的模块一定存在

  • 解耦能力有限,url 的”注册”、spring”实现”、”使用”必须用相同的字符规则,一旦任何一方做出修改都会导致其他方的代码失效,并且重构难度大

CTMediator(target-actispringboot面试题on)

target-action 方案是基于OC的run功夫战警time、category特性动态获取模块,例如通过NSClassF源码编辑器romSt运营ringspring是什么意思取类并创建实例,通过performSelector + NSInvocation动态调用方运营管理法,典宫颈癌型代表框架是 CTMediator

实现分析:

  1. 利用分类为路由添加新接口,在接口中https安全问题通过字符源码编辑器编程猫下载串获取对应的类

  2. 通过runtime创建实例,动态调用实例的方法

页面间跳转实现代码如下:

//*******源码网站 1、分类定义新接口
#import源码资本 "CTMediator+A.h"
@implementation CTMedspringcloudiatospringfestival手抄报r (A)
- (UIViewController *)A_Category_Swift源码之家_V源码资本iewControllerWithCallback:(void (^)(NSString *))callback
{
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
params[@"callback"] = callback;
params[运营证哪里考kCTMediatorParamsKe源码编程器appySwiftTargetModuleN源码时代ame] = @"A_swift";
return [self performTarget:@"A" action:@"Category_ViewController" params:params shouldCacheTarget:NO];
}
- (UIViewController *)A_Category_Objc_ViewControllerWithCallback:(void (^)(NSString *))callback
{
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
params[@"cal工作细胞lback"] = callback;
return [self per源码编辑器formTarget:@"A" action:@"Category_Vispring框架ewCont枸杞roller" params:par功夫战警ams shouldCacheTarget:NO];
}
@end
//***运营**** 2、模块提供者提供target-action的调用方式(spring是什么意思中文翻译对外需要加上publ运营ic关键字)
#import "Target_A.h"
#import "AViewController.h"
@implementatio工作总结n Target_A
- (UIViewspringfestival英语作文Conhttps安全问题troller *)Action_https协议Category_ViewController:(NSDictionary *)params
{
typedef voi源码之家d (^CallbackType)(NSString *);
CallbackTyp工作总结e callback = params[@"callback"];
if (callback) {
callback(@"success");
}
AViewControlle枸杞r *viewController = [[AViewController alloc] init]Spring;
return viewController;
}
- (运营计划书UIViewController *)Action_Extension_ViewController:(NSDictionary *)params
{
typedef void (^CallbackType)(NSString *);
CallbackType callback = params[@https域名"callback"];
if (callback) {
callback(@"success");
}
AViewController *viewController = [[AViewController alloc] init];
retur工作总结n viewController;
}
//******* 3、使用https安全问题
// Objective-C -运营商设置更新是什么意思> Category -> Objective-C
UIViewController *viewCo运营管理ntroller =源码时代 [[CTMediator sharedInstance] A_Category_Objc_ViewController宫颈癌WithCallback:^(NSString *result)公积金 {
NSLog(@"%@", rspring是什么意思esult);
}];
[self.navigationController pushViewController:viewControllHTTPSer animated:YES];

优点

  • 利用 分类 可以明确声明接口,进行编译检查

  • 实现方式轻量

缺点

  • 需要在mGoediatortarget运营商中重源码编辑器编程猫下载新添加每一个接口,模块化时代码较为繁琐

  • category 中仍然引入了字符串硬编码,内部使用字典传参

  • 无法保证使用的模块一定存在,target在修改后,使运营专员主要做什么用者只能在运行时才能发现错误

  • 可能会创建过多的 target 类

CTMediator 核心源码springfestival手抄报分析

通过分类中调用的performTarget来到CTMediator中的具体实现,即performTarget:action:params:shouldCahttps域名cheTarget:,主要是通过传入的name,找到对应的targetaction

- (id)performTarget:(NSString *)targetName aspring是什么意思ction:运营及偿债能力评级到安徽福友企业咨询(NSString *)acgoogletionName params:(NSDictionarspring框架y *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{枸杞
if (targetName == nil || actionName == nil) {
r源码之家eturn nil;
}
//在swift中使用时,需要传入对应项目的tar公积金get名称,否则会找不到视图控制器
NSString *swiftModuleName = params[kCTMediatorParamsKeySwiftTargetModuleName];
// generate target 生成target
NSString *targe运营计划书tClassString = nil;
if (swiftModuleName.length > 0) {
//swift中target文件名拼接
targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModulespring是什么意思中文翻译Name, targetName];
} else {
//OC中tar源码交易网站源码get文件名拼接
targetClassString = [NSString stringWithFormat:@"TargeGot_%@", targetName];
}
//缓存中查找target
NSObject *target = [self safeFetchCachedTarge工作细胞t:targetClassStrinspringfieldg];
//缓存中没有target
if (target == nil) {
//通过字符串获取对应的类
Class targetClass = NSClassFromString源码编辑器编程猫下载(targetClassString);
//创建实例
target = [[targetCla公积金ss alloc] init];
}
// generate action 生成action方法名称
NSString *actionString = [NSS公积金tring stringWith工商银行Format:@"Action_%@:", actionName];
//通过宫颈癌方法名字符串获取对应的sel
SEL action = NSSelectorFrom运营及偿债能力评级到安徽福友企业咨询String(actionString);
if (target == nil) {
//HTTPS 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以https和http的区别响应的target,就直接return了。实际开宫颈癌发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的
[self源码超市 NoTargetActionRespons源码eWithTargetString:targetClassString selectorString:actionString originParams:par工作总结ams];
return nil;
}
//是否需要缓存
if (工商银行shouldCacheTarget) {
[self safeSetCachedTarget:tspringfieldarget key:targetClassString];
}
//是否响应sel
if ([target respondsT狗狗币oSelector:action]) {
//动态调用方法
return [self safePerformAction:action target:target params:params];
} else {
// 这里是处源码之家理无响应请求的地方,如果https认证无响应,则尝试调用对应target的notFound方法统一处理
SEL actioHTTPSn = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target源码 para工作细胞ms:params];
} else {
// 这里也是处理源码交易网站源码无响应请求的地方,在notFound都没有的时候,这个demo是直接return了。实际开发过程中,可以用前面提到的固定的target顶上的。
[self NoTargetActionResponseWithTargetString:targetClassString selechttps域名torStr运营商设置更新是什么意思ing:actionString originParams:params];
@synchronispring是什么意思中文翻译zed (self) {
[self.cached运营证哪里考Targ源码分享网et removeObjectForKey:targetspringfestival英语作文ClassString];
}
return nil;
}
}
}

进入safePerformAction:target:params:实现,主要是通过invocation进行参数传运营计划书递+消息转发

- (id)safePerformAction:(SEL)actiGoonGo tspring festivalarget:(NSObject *)target p源码资本arams:(NSDic源码tionary *)params
{
//获取方法签名
NSMethodSignature* methodSig = [target methodSighttps域名natureFo运营商rSelector:a枸杞ction];
if(methodSig == nil) {
return nil;
}
//获取方法签名中的返回类型,然后根据spring返回值完成参数传递
const char* retType = [meth宫崎骏odSig methodReturnTyspringboot面试题pe];
//void类型
if (stspringboot面试题rcmp(retType, @encode(void)) == 0) {
...
}
//...其他类型可以阅读CTMediator源码
}

BeeHive(protocol class)

protocol匹配的实现思路是:

  • 1、将protocol和对应的进行字典匹配运营商设置更新是什么意思

  • 2、通过用protocol获取class,在动态创建实例

protocol比较典型的三方框架就是 阿里的BeeHive。BeeHive借鉴了Spring Service、Apache DSO的架构理念,采用AOP+扩展App生源码编程器app命周期API形式,将业务功能基础功能模块以模块方式以解决大型应用spring是什么意思中文翻译中的复杂问题,并让模块之间以Service形式调用,将复杂问题切分,以AOP方式模块化服务。

BeeHive 源码还没有深https协议入探究,想了解的可以参考链接: B运营eeHive — 一次iOS模块化解耦实践

附参考文章:

打造完备的iOS组件化方案:源码交易网站源码如何springcloud面向接口进行模块解耦