iOS CTMediator组件化实践

3篇文章带你学会组件化😁😁😁
1.iOS 创建远程cocoapods 私有库
2.iOS Pod 私有库创建(自定义的组件)
3.iOS CTMediator组件化实践

首先你要懂得组件化的整体思想,如下图,就是通过一个中间者传递信息,用来降低模块间的耦合度, 从而达到高内聚低耦合的目的.

组件化思想

提到的中间层就是CTMediator, GitHub上面介绍的非常详细, 还有使用文章推荐.

废话不多说, 开始实践:

  • 目的: 项目的ViewController 的touchesBegan方法push 新界面(AViewController); 分解成通过CTMediator 和组件通信获取aVc , 来达到相同功能.
    普通->组件

步骤详解

1. 创建组件A_Section, 可参考前一篇文章自定义组件

  1. GitHub 上创建A_Section组件远程仓库
  2. 创建本地项目 (pod lib create A_Section)
  3. 修改.podspec 文件中的homepage 和source 和version
#发版版本号,每更新一次代码就改变一次版本号
s.version      = "0.0.1"
#你的 git 仓库首页的网页 url,注意并不是 https/ssh这种代码仓库地址
s.homepage     = "https://xxxxxxxxx/A_Section"
#这里就是你 git 仓库的 https/ssh 地址了
s.source       = { :git => "git@gitxxxxxxxx/A_Section.git", :tag => "#{s.version}" }
  1. 创建AViewController 和 Target_A 文件, 在选择文件夹的时候记得选classes
    组件内添加内容

    : 一个组件对应一个 Target_A, 这里要特殊记忆下Target_AAAction_viewControllerviewController ;
// Target_A.h文件
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Target_A : NSObject

/// 获取该组件的AViewController 的实例化对象
- (UIViewController *)Action_viewController:(NSDictionary *)params;

@end

// Target_A.m 文件
#import "Target_A.h"
#import "AViewController.h"

@implementation Target_A

- (UIViewController *)Action_viewController:(NSDictionary *)params
{
    AViewController *viewController = [[AViewController alloc] init];
    return viewController;
}

@end
  1. 这时的A_Section工程目录应该是这样的:
    当前工程目录
  2. 提交组件项目更新内容, 组件发版打tag, 将repo源添加到自己的私有repo索引库中.可参考自定义组件5~8步骤

2. 创建中间件A_Category(CTMediator 的Category)

  1. 同一业务模块使用同一中间件就可以, 这里只是文件夹名称, 可随意, 这里使用A_Category
  2. 创建远程仓库A_Category
  3. 修改.podspec 文件, 依赖CTMediator 第三方库
  4. cd /A_Section/Example 目录下, 更新(pod update --no-repo-update)
  5. 创建CTMediator 的分类CTMediator+A
  6. CTMediator (A)内部实现如下:
// CTMediator+A.h 内容
#import <CTMediator/CTMediator.h>
@interface CTMediator (A)
- (UIViewController *)getAViewController;
@end

// CTMediator+A.m 内容
#import "CTMediator+A.h"
@implementation CTMediator (A)
- (UIViewController *)getAViewController
{
    /*
        AViewController *viewController = [[AViewController alloc] init];
     */
    // 这个方法就牛逼了, CTMediator 会自动去找Target_A 的类, 并且去寻找是否存在viewController 方法, 存在就去实现
    return [self performTarget:@"A" action:@"viewController" params:nil shouldCacheTarget:NO];
}
@end

: 还记得步骤一第四小步需要特殊记忆的Target_AAAction_viewControllerviewController吗? 其实对应的就是performTarget:@"A"中的Aaction:@"viewController"中的viewController , 名字都可以随便起, 但是必须是在对应的前提下;

  1. 配置之后的文件结构:
    A_Category结构目录
  2. 提交组件项目更新内容, 组件发版打tag, 将repo源添加到自己的私有repo索引库中.可参考自定义组件5~8步骤

3. 本地创建主工程MainProject

  1. 就是创建个名字为MainProject(名称可随意) 的Xcode项目, pod init -> pod install 操作完成即可.
  2. 尽量保证A_Section 和A_Category 和MainProject 在同一文件夹下或同级目录下, 方便后续操作.
    我的文件位置, 都在桌面上了

4. 本地组件测试

  1. cd至MainProject目录下, 修改profile 文件:
target 'ManiProject' do
  use_frameworks!

    #组件化依赖
    pod 'CTMediator'
  
    #本地测试
    pod 'A_Category', :path => '../A_Category'
    pod 'A_Section',  :path => '../A_Section'

end

: pod 'A_Category', :path => '../A_Category'代表在当前的podfile目录下, (../)返回上一级目录, 找到A_Category文件, 拉取其中A_Category.podspec文件.

  1. 更新库文件( pod install)
  2. 测试组件是否能正常使用, MainProject中的ViewController 类中测试push 功能
// ViewController.m文件内容
#import "ViewController.h"

// 引入中间件头文件
#import <A_Category/CTMediator+A.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // aVc 其实就是AViewController
    UIViewController *aVc = [[CTMediator sharedInstance] getAViewController];
    [self.navigationController pushViewController:aVc animated:YES];
}
@end

: 引入A_Category的头文件, 通过[[CTMediator sharedInstance] getAViewController]获取组件提供的东西.

这个时候能正常实现push 功能, 就算本地的组价可以正常使用了.

4. 远程仓库的组件的使用测试

  1. 修改podfile 文件, 添加私有源repo索引库.不会的话可参考创建远程cocoapods 私有库
  2. 添加需要使用组件的依赖
    podfile 文件大致为:
#这是GitHub的源索引库
source 'https://github.com/CocoaPods/Specs.git'
#这是我自己的组件的源索引库
source 'git@github.com:LiHe0308/PrivateSpecs.git'

target 'ManiProject' do
  use_frameworks!

    #组件化依赖
    pod 'CTMediator'
  
    #组件
    pod 'A_Category'
    pod 'A_Section'

end
  1. 主工程pod install 更新库文件
  2. 测试push 功能, 代码一点不需要变

这时候功能正常, 就代表远程组件可以正常使用了.

总结注意点:

  • 主工程、组件、之间的关系

 1. 组件A_Section: 将相当于正常开发的一个文件夹, 但是多了一个Target_A类, Target_A中对外(CTMediator 的分类)开放整个组件的功能,所以整个组件的功能都写在Target_xName中.例:
 - (UIViewController *)Action_viewController:(NSDictionary *)params;
 
 2. A_Category: 主要是使用CTMediator 的分类,CTMediator (A), 重点就是命名, 一定要和组建中Target后面的名称相同, 也就是A.
    通过方法return [self performTarget:@"A" action:@"viewController" params:nil shouldCacheTarget:NO];实现和组件通信, 获取自动寻找Target_A 文件中的viewController 来执行
    然后封装方法 - (UIViewController *)getAViewController; 供外界使用.
 
 3. 主工程ManiProject: 就是你所做的项目, 它只与CTMediator (A)通讯, 引入头文件,
    通过分类中自定义的方法[[CTMediator sharedInstance] getAViewController]; 获取到组件
  • 代码的提交顺序, 严格遵守!!!

 1. 一定要先提交所有变更信息
 git remote add origin git@github.com:xxx.git
 git add .
 git commit -a -m "提交变更信息"
 git push -u origin HEAD
 
 2. 修改xxxxx.podspec 文件中homepage 和 source, 一定要准确
    s.homepage   ->  你的 git 仓库首页的网页 url,注意并不是 https/ssh这种代码仓库地址
    s.source     ->  这里就是你 git 仓库的 https/ssh 地址了
 
 3. 修改s.version
    s.version = 0.2.0
 
 4. 发版 -> 一定要与.podspec 文件中s.version 相同
 git tag 0.2.0
 git push origin 0.2.0
 
 5. 将组建repo 地址推到私有源索引库中 (只做一次就可以, 且必须在.podspec同级目录下操作)
 pod repo push [私有源名称] 组件名称.podspec --allow-warnings
  • 关于 xib 和图片

组件中若用到了图片,或者 xib 资源,要指定资源的文件路径,否则不会把图片打包到你的组件中:

s.resource_bundles = {
    'A_Section' => ['A_Section/AImages/**/*.{png}', 'A_Section/Classes/*.{xib}']  
}
或者
s.resources = ['A_Section/AImages/**/*.{png}', 'A_Section/Classes/*.{xib}']

如果使用 Xocde 工程自带的 Assets 那个文件夹的话,图片也无法打包到组件中,最好自己重新创建一个新的文件夹用来存放图片资源;
然后代码中获取 xib, png 等 resource 时,bundle 重新设置,这样就保证了无论在组件中,还是在 MainProject 工程中,都可以配置到正确的 Bundle,如果你使用 s.resource_bundles={},配置了自定义的 bundle名称,那么 [bundle pathForResource:@"A_Section" ofType:@"bundle"]中就要替换成相应的名称.

//mainBundle
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *bundlePath = [bundle pathForResource:@"A_Section" ofType:@"bundle"];
    if (bundlePath)
    {
       //组件资源所在的 bundle     
       bundle = [NSBundle bundleWithPath:bundlePath];
    }

.End

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

推荐阅读更多精彩内容