OC底层原理39:组件化(一)方案

张建 lol

组件化方案

常用的组件化方案主要有两种:

  • 本地组件化:主要是通过在 工程中创建library,利用 cocoapodsworkspec 进行本地管理,不需要将项目上传git,而是直接在本项目中以 framework 的方法进行调用

  • cocoapods组件化:主要是利用 cocoapods 来进行管理模块的 远程管理,需要将项目上传git(需要注意:这里的组件化模块分为 公有库私有库,对公司而言,一般是 私有库

本地组件化

创建主工程

  • 首先创建一个名为 Modularization 的工程

  • 集成 cocoapods,进行本地管理
1
2
3
4
zhangjian@zhangjiandeMBP ~ % cd /Users/zhangjian/Desktop/Modularization 
zhangjian@zhangjiandeMBP Modularization % pod init
Ignoring ffi-1.13.1 because its extensions are not built. Try: gem pristine ffi --version 1.13.1
zhangjian@zhangjiandeMBP Modularization % pod install

创建组件

假设有以下几个模块

  • 主工程:承载主要的表层业务代码

  • Core:独立存在,应用加密、接口请求等敏感代码

  • Base:基类封装,拓展,基本的数据处理

  • Service:服务层,封装业务工具类,例如网络层服务、持久化服务等

  • Pods:三方依赖

其中,各个模块间的关系如下图

下面,我们来进行模块的创建,以 Core 模块为例:

  • 选择 File -> new -> project -> iOS -> Framework,新建一个 ZJCore 模块

  • 选择正确的 GroupWorkSpace(这里注意:创建的 library 最好放在 主工程根目录下,否则后续的 podfile 执行 pod install 会报错)

创建成功后,看到的结果如下:

  • 将创建的 libraryBuild Settings -> Mach-O Type 修改为静态库 Static Library

主工程调用Library

  • ZJCore 中新建一个文件,并添加如下代码
1
2
3
4
5
6
7
@interface ZJCoreSetting : NSObject
// 声明属性
@property (nonatomic,copy)NSString * name;
@end

@implementation ZJCoreSetting
@end
  • Build Phases -> Headers -> Public 中将新建的文件拖拽到 Puclic 中,这样主工程才能访问该文件

  • 在ZJCore文件中添加引用

  • 在主工程中,选择 target -> Frameworks,Libraries,and Embedded Content -> + 号 -> 添加 ZJCore,只需要build主工程,library能够自动联编

使用

首先 #import <ZJCore/ZJCoreSetting.h>,然后使用

这里需要注意的是,子library之间的互相调用,与主工程调用library类似,主需要添加依赖、暴露header即可

使用cocoapods管理三方依赖

假设我们需要在 ZJCore 中封装网络层代码,需要用到三方库 AFNetworking,在podfile中有如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

################# 三方依赖
# 网络
def network_layer_pods
pod 'AFNetworking'
end

################# 模块
target 'ZJCore' do
# 配置libray路径
project 'ZJCore/ZJCore.xcodeproj'

network_layer_pods

end

################# 主工程
target 'Modularization' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

network_layer_pods

# Pods for Modularization

end
  • 终端 pod install ,然后等待成功,成功后你可以在 ZJCore 模块中引用头文件 #import <AFNetworking.h> 并使用三方库如下:

到此,一个本地组件化的模块就配置完成了

cocoapods组件化

除了本地组件化,还可以使用 cocoapods,其原理如下图所示

这里还是以本地组件化中的结构为例

创建私有仓库

  • github 上创建一个 MySpecs 仓库

具体步骤:登录github -> 点击右上角+号 -> new reponsitory -> 输入 repository name 为 MySpecs,选择仓库类型为 private,点击 Create reponsitory

  • 将私有仓库添加至本地 ~/.cocoapods/repos 目录
1
pod repo add MySpecs git@github.com:13718004742/MySpecs.git

查看添加结果

创建pods工程,即组件化工程

  • 使用终端创建 ZJServices 模块
1
2
% cd Desktop 
% pod lib create ZJServices
  • 根据提示一次输入:iOS、Objc、Yes、None、No、ZJ

  • 进入模块的目录,将文件拷贝至 ZJServices -> Classes 中,删掉 ReplaceMe.m -> 替换成你封装好的文件

  • 执行 pod install,会将 Classes更新至pods中
1
2
% cd /Users/zhangjian/Desktop/ZJServices/Example
% pod install

成功后,查看工程结构如下:

配置pods工程

修改模块的配置文件,即 ZJServices.podspec

  • 如果需要依赖三方库,需要配置 s.dependecy
1
s.dependency 'AFNetworking', '~> 4.0.1'
  • 如果模块间需要相互引用,同样需要配置 s.dependency,以 ZJCore 为例,需要引用 ZJService,在桌面以同样的方式再次创建一个 ZJCore,然后修改如下:
1
2
// 1.修改 podspec 文件
s.dependency 'ZJServices'

1
2
// 2. 修改podfile 文件
pod 'ZJServices', :path => '../../ZJServices'

  • 如果需要加载资源,如 图片/json/bundle 文件等

    • 在模块的 Assets 文件夹中添加资源文件
    • specs 里配置资源路径(必须配置!!否则无法读取资源)
    • 访问时需要指定资源文件路径
1
2
3
4
// 1. 修改 podspec 文件,自动创建ZJCore.bundle
s.resource_bundles = {
'ZJCore' => ['ZJCore/Assets/*.png']
}

ZJCore 为显示的图片资源的 bundle 名字,在本地会显示 ZJCore.bundle,这个 可以自定义ZJCore/Assets 为图片文件目录,回到 ZJCoreExample 模块,安装 pod install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 2. 使用
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
imgView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:imgView];

//到指定目录
NSURL * bundleURL = [[NSBundle mainBundle] URLForResource:@"Frameworks" withExtension:nil];
bundleURL = [bundleURL URLByAppendingPathComponent:@"ZJCore"];
bundleURL = [bundleURL URLByAppendingPathExtension:@"framework"];
if (bundleURL) {
NSBundle *imgBundle = [NSBundle bundleWithURL:bundleURL];
bundleURL = [imgBundle URLForResource:@"ZJCore" withExtension:@"bundle"];
if (bundleURL) {
NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
NSInteger scale = [[UIScreen mainScreen] scale];
NSString *imgName = [NSString stringWithFormat:@"%@@%zdx.png", @"zj",scale];
imgView.image = [UIImage imageWithContentsOfFile:[bundle pathForResource:imgName ofType:nil]];
}
}

默认情况下,图片资源在 Frameworks 下的 ZJCore.framework 下的 ZJCore.bundle 包中,右键打开包内容,即可看到 zj@2x.png 图片,如下图:

  • 同理,模块中的json文件的获取方式也是一样的

提交至git

这里提交至git的模块是pods工程才可以,以 ZJCore 为例

  • 需要在github上创建一个私有repository,命名为 ZJCore

  • 执行以下终端命令

1
2
3
4
5
6
7
8
9
10
11
12
$ git init
$ git add .
$ git commit -m "第一次提交"
// 即第一个步骤中创建的仓库地址
$ git remote add origin git@github.com:13718004742/ZJCore.git
// 查看当前主分支名
$ git branch
$ git push -u -f origin master
// 一定要有标签,不然会有下面的警告
// podspec文件中获取Git版本控制的项目需要tag号, % git tag -d rm 表示删除
$ git tag "0.1.0"
$ git push --tags

验证podspec文件

执行终端命令 pod spec lint,注意:pod spec 相对于 pod lib 会更为精确

* pod lib 相当于只验证一个本地仓库
* pod spec 会同时验证本地仓库和远程仓库
1
% pod spec lint --allow-warnings

如果出现如下错误

解决办法将 podspec 文件下的所有 https://... 均改为 git@github...

提交到私有仓库

执行 pod repo 查看本地 MySpecs Repo

执行以下命令

1
2
3
// pod repo push [本地Spec Repo名称][podspec文件路径]
// 举例
$ pod repo push MySpecs ZJCore.podspec --verbose --allow-warnings

提交成功后,可在本地仓库中看到提交路径 MySpecs -> ZJCore

模块化

  • Classes -> 创建模块 UIView、UILabel等,并在各模块内存放你想拷贝的代码文件,如下图

  • 上传改动到远程仓库
1
2
3
4
5
6
7
$ git add .
$ git commit -m "xxx"
$ git push origin master
// tag 值增加
$ git tag 0.x.x
//推送tag到服务器上
$ git push --tags
  • 修改.podspec

使用

  • 新建一个 ZJDemo 工程,在项目的 podfile 里面添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

# 私有库ZJCore
source 'git@github.com:13718004742/MySpecs.git'

target 'ZJDemo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# 私有库ZJCore
pod 'ZJCore'

# Pods for ZJDemo

end
  • 执行 pod install 即可
  • Post title:OC底层原理39:组件化(一)方案
  • Post author:张建
  • Create time:2021-06-22 14:50:12
  • Post link:https://redefine.ohevan.com/2021/06/22/OC底层原理/OC底层原理39:组件化(一)方案/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.