前言
一、需要问题考虑:消息型的还是URL型的?配置化还是自注册?现有模块功能完善独立?借用框架还是自行实现?数据传递链的设计?如何回调?……
二、最通用的模块化实现:模块化调度中心(router),通过共享数据模型、协议降低模块间耦合,统一block回调、公用组件可直接引入使用,也可通过调度中心调用。
参考资料 https://www.yuque.com/ioser/spb08a/yi6ppl
模块架构设计目录说明
image模块化实现代码示例
调用
<pre data-language="plain" id="GffX9" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);"> SWMediaParam *param = [[SWMediaParam alloc] init];
param.type = SWMediaParamTypeOfVideo;
[SWUrlRouter openUrl:kSWMediaUrl withParam:param completion:^(NSError *error, id dic) {
NSLog(@"completed:%@",dic);
}];
</pre>
模块调度
<pre data-language="plain" id="cnbTL" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">/// 注册路由
/// @param handlerClass 模块类
/// @param url 路由
- (void)registHandlerClass:(Class<SWUrlHandlerProtocol>)handlerClass forUrl:(NSString *)url;
/// 调用路由实现模块功能
/// @param url 路由
/// @param param 传入参数
/// @param callback 模块回调
- (void)openUrl:(NSString *)url withParam:(id)param completion:(SWUrlHandlerCallback)callback;
- (BOOL)canOpenUrl:(NSString *)url;</pre>
模块通讯
<pre data-language="plain" id="IgeM1" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">///通讯协议
- (void)handleUrl:(NSString *)url withParam:(id)param completion:(SWUrlHandlerCallback)callback;</pre>
路由定义
<pre data-language="plain" id="AGj4s" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">static NSString *const kSWMediaUrl = @"SuperWomgs://Media";//音视频模块</pre>
创建一个模块
现在我们知道了什么可以成为模块,让我们创建一个。则需要创建一个特定的依赖项,以表示我们应用程序的核心概念。我称它为Core。
首先,我创建一个动态框架项目。
导入模块
创建依赖项后,我们可以将其包含到我们的应用程序中。对于这一部分,我首先创建了一个工作区,这使得一次处理两个项目变得更加容易。
我向工作区以及我的核心模块添加了一个应用程序。它们尚未链接。
为了在应用程序中导入Core框架并能够使用它,我只将框架文件拖放到主应用程序的部分中。Linked Framework and Libraries
模块依赖管理
处理依赖关系的另一个角度是创建一个伞形框架,以将每个依赖关系嵌入到一个程序包中,以限制构建并保持整洁的工作空间。 使用CocoaPods,已经做到了。
git管理
概念
1.code repository 代码仓库,主要存放我们提交的代码
2.spec repository 配置仓库,所有的配置按照包名、版本号存放在这个仓库。这个仓库只用来存放.podspec文件,不存放代码。
一、gitLab 创建 spec配置仓库 和代码 Code 仓库
创建配置仓库 管理所有模块
image创建每个模块代码 Code 仓库
image二、创建 pod 库
在本地文相应件夹 创建SWPublic模块 仓库名为SWPublic
执行以下命令要 可能要几分钟的时间才能完成
<pre data-language="plain" id="XAnlJ" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">pod lib create SWPublic</pre>
完成创建后会有以下终端提示 配置 pod 库
<pre data-language="plain" id="QOlOh" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);"># 选择使用平台
What platform do you want to use?? [ iOS / macOS ]
iOS
选择编程语言
What language do you want to use?? [ Swift / ObjC ]
ObjC
在你的项目中是否创建一个demo工程
Would you like to include 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 ]
No
类的前缀
What is your class prefix?
GS</pre>
- 所有的配置都配置完后,会自动打开我们当前的 pod 库。
- image
pod 项目结构
系统会自动打开一个 Xcode 工程,具体的结构如下,XXX.podspec为我们的配置文件。
image三、podspec 项目配置
<pre data-language="plain" id="hPmzN" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">Pod::Spec.new do |s|
# pod search 搜索的关键字,不需要手动改变
s.name = 'SWPublic'
版本号,注意,需要和我们代码里的tag保持一致
s.version = '0.1.0'
简介
s.summary = '基础库'
详细描述
s.description = <<-DESC
基础库 一般存放通用的跨模块的代码
DESC
项目主页地址,必须是可以访问的地址
s.homepage = 'https://gz-gitlab.vipthink.cn/'
s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
许可证
s.license = { :type => 'MIT', :file => 'LICENSE' }
作者
s.author = { 'Tony0822' => 'XXXXXX(会自动生成)' }
项目地址
s.source = { :git => 'https://gz-gitlab.vipthink.cn/fly/front/app/ios/swpublic.git', :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '8.0'
源码文件的配置路径,所有的代码都在这个目录下
s.source_files = 'SWPublic/Classes/*/'
资源文件的配置路径
s.resource_bundles = {
'GSWebviewLib' => ['SWPublic/Assets/*.png']
}
源码头文件的配置路径
s.public_header_files = 'Pod/Classes/*/.h'
系统框架的依赖库
s.frameworks = 'UIKit', 'MapKit'
第三方框架的依赖库
s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'YYKit'</pre>
验证
验证 podspec 文件,编辑完 podspec 文件需要验证一下这个文件是否可用 podspec 文件不允许有任何的 warning 或者 error
注意如果有多种依赖关系(如SWMediaPlayer模块依赖了自己的SWPublic) 需要指定源
pod lib lint --sources=https://gz-gitlab.vipthink.cn/fly/front/app/ios/mudule-specs.git,'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
<pre data-language="plain" id="RC8gV" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">pod lib lint
--allow-warnings 允许有任何的Warning
--verbose 获取更多错误信息
--use-libraries 包含.a 需要添加此参数:</pre>
将模块代码发到存放代码路径 然后cd到Example文件 执行 pod install 检验是否拉到代码
imagepod 成功后 至此本地仓库已完成
四、提交代码到远端 关联仓库
将模块代码提交到远程仓库 可能用到的 shell
<pre data-language="plain" id="L55fr" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">git init//初始化
git status//查看状态
git add .//添加文件到缓冲区
git commit -m "描述"//从缓冲区提交代码到仓库
git tag -a '0.0.1' -m '描述'//添加tag
git tag //查看tag
git tag -d '0.0.1'//删除tag
git remote add origin https://gz-gitlab.vipthink.cn/fly/front/app/ios/swpublic.git//关联本地仓库和远程仓库。
git push -f origin master//将本地库的代码推到远程库
git push --tags//将本地创建的tag推到远程库
git push origin :0.0.1//删除tag</pre>
遇到的问题
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://gz-gitlab.vipthink.cn/xchaos/ios/wdpublic.git'
项目配置修改 : 点击进入Protected branches,点击unprotected将master分支的权限改变,即关闭master的protected权限
参考: https://www.cnblogs.com/cppeterpan/p/7289266.html
临时解决方案 第一次推送成功后 protect 权限改回来防止他人修改
五、创建索引库
1.pod repo 查看本地索引库
image查看是否已经有了所以需要的索引库
没有用以下指令创建 XXXSpec 对应我上面的所需要的SuperWings 名字可以自定义一般区分于项目名
pod repo add XXXSpec 远程索引库的gitlab的地址
创建完成之后可以用pod repo 查看是否成功 或者 ~/.cocoapods/repos查看是有有对应的文件夹
image六、将代码提交到远程仓库后 执行 仓库配置关联
<pre data-language="plain" id="FOIdd" class="ne-codeblock" style="border: 1px solid rgb(232, 232, 232); border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">pod repo push XXXSpec SWPublic.podspec --allow-warnings
注:XXXSpec 为创建索引库时的name,SWPublic.podspec为创建本地库时的name
例子:pod repo push SuperWings SWPublic.podspec --allow-warnings</pre>
执行完上述shell 会生成对应的版本管理
image
网友评论