背景
在组件化之前,小花钱包 App 项目代码,在代码结构,代码质量和层级划分上都处于一个比较乱的状态。这样的项目条件在业务发展不是很快的时候,是可以适应需求的,并且能一定程度地保证开发效率。但随着业务方向的多样和产品需求的快速迭代要求,这时单一工程开发模式就会显露出一些弊端:耦合比较严重(因为没有明确的约束,「组件」间引用的现象会比较多)
容易出现冲突,包括代码冲突和布局冲突等情况(尤其是使用 Xib和storybord,还有就是 Xcode Project)
项目拓展性不高,复用和可移植性不强
业务方的开发效率不够高(只关心自己的组件,却要编译整个项目,与其他不相干的代码糅合在一起)
为了解决这些问题,就采取了「组件化」策略,注:这里的组件化,也就是大家说的『模块化』,不是在主工程中用文件夹来区分模块,而是指将独立模块抽调成 CocoaPods 库、或者其他形式的库文件,成为一个独立工程,每个组件即代表一个 CocoaPods 私有库。
一、为什么要组件化?有哪些优势?
1.组件和组件之间没有明确的约束;
2.组件化采用cocoapod管理,同属于git私有库,便于代码复用和管理,解决人多(更好的协作)、需求多(更好的功能模块划分)的问题;
3.组件单独开发、单独测试,不用揉入主项目中开发,测试也可以针对性的测试;
4.解决项目模块间的代码耦合问题;
5.自由选择开发姿势(MVC / MVVM)
6.提高业务开发效率
二、怎么划分组件化?
1.基础组件
1.按功能分库,不涉及产品业务需求,跟库Library类似
2.通过良好的接口供上层业务组件和功能组件调用
3.不写入产品定制逻辑,通过扩展接口完成定制
2.功能组件
1.App产品内定制通用组件;(各个业务模块依赖使用,但需要保持好定制扩展的设计)
2.公共通用组件,能够完成某个功能点,例如轮播器组件;
3.对外暴露数据交互接口,内部实现细节只有组件自己清楚,数据交互方面一般使用代码、block和属性来完成,不建议组件中使用通知进行交互,不利于维护管理;
3.业务组件
1.业务功能间相对独立,相互间没有Model共享的依赖;
2.业务之间的页面可以直接进行跳转;
3.业务之间的逻辑Action调用只通过由当前业务模块提供,各自与后台交互;
三、组件化工程需要解决的问题
资源打包
1.对于 UI 界面,需要做的是资源打包,在模块拆分中,要非常注意资源分割。因为业务模块的划分,不仅仅是是代码抽出,也有资源抽出。
2.资源库包括但不仅限于:.xib 文件、声音资源、图片资源、纯文本文件以及视频资源
3.所有的资源文件,应当单独创立 Res 文件夹,放入其中,并在 .podspec 中表明资源文件路径 s.resources = ["Source/*/.xib", "Source/Res/*.xcassets"]
四、组件维护问题?
1.gitLab统一管理
2.组件的维护持续更新是需要一直做的,完善组件功能,优化组件性能,提高组件适用范围
3.组件的管理跟git的tag是一一对应,每个tag版本都要有对应的记录
实操部分(以网络库组件为例说明)
一、 设计理念
关于网络通信模块的设计,我个人认为应该是每一个HTTPS请求都应该独立互不干扰,就是你封装的POST/GET方法都会创建一个临时的对象,而长连接一般只维持一个实例对象采用单例的方式创建。我会为每一个HTTPS 接口请求创建一个API对象,在里面请求数据,当然了为了避免请求代码的重复编写可以建立一个BASE API类,子类调用父类的请求方法就行了,不同的只是接口与参数。
二、 终端操作,组件创建
准备工作(中心库的创建)
1.首先在gitLab上创建一个项目存放私有Repo源,repo地址https://code.xhqb.io/appComponent/XHSpecs.git ,这个地址也叫中心库,以后私有组件都会存放在这里;
2.本地添加私有源 终端执行命令pod repo add XHSpecs https://code.xhqb.io/appComponent/XHSpecs.git(这个步骤已经完成,后续无需再执行)
3.以上操作完成 进入~/.cocoapods/repos目录下至少会有2个文件夹XHSpecs和master, master文件下面存放的是公有源文件,XHSpecs目录下存放我们私有源文件
4.基本准备工作完成 #### 创建组件项目(以 XHNetwork 为案例)
1.0 新建项目XHNetwork,并在XHNetwork.xcodeproj同级目录中添加Classes文件夹,用来存放pod需要导入的文件。
2.0 终端cd至XHNetwork目录下执行命令pod spec create XHNetwork。
3.0 执行命令vim XHNetwork.podspec编辑podspec文件,具体如何编辑可参考第三部分spec文件写法说明。
4.0 编辑完成XHNetwork.podspec文件之后,执行pod lib lint --allow-warnings命令,进行本地验证,验证通过执行以下步骤。
5.0 执行git操作:
5.1 git add .
5.2 git commit -m 'log'
5.3 git remote (如果没有分支origin,执行5.3.1命令)
5.3.1 git remote add origin https://code.xhqb.io/appComponent/XHNetwork.git
5.4 git push origin master
5.5 git tag -a 'version' -m 'log' tag一定要和podspec中的version一致
5.6 git push --tags --tags为了把刚才添加的tag提交上去
6.0 执行命令 pod spec lint --allow-warnings 此步骤同步骤4操作一致,步骤4为本地验证,步骤6为spec文件验证,会注册验证结果
6.1 如果此私有组件依赖于其他私有组件,那么执行命令改为 pod spec lint --allow-warnings --source=https://code.xhqb.io/appComponent/XHSpecs.git,命令后面跟上私有源地址
7.0 执行命令pod repo push XHSpecs XHNetwork.podspec --verbose --allow-warnings 注:XHSpecs即私有源中心仓库,此步骤为将验证成功的podspec索引文件上传到中心库
7.1 如果步骤6命令有跟私有源地址,那么此命令也应该加上私有源地址
8.0 除了步骤6和步骤7这种验证上传方式,另外提供trunk验证方式;
8.1 pod trunk register 邮箱地址 ‘用户名’ —verbose //邮箱注册trunk
8.2 进入邮箱,点击trunk链接验证
8.3 验证成功之后,执行 pod trunk push XHNetwork.podspec ####
三、spec文件写法说明
Pod::Spec.new do |s|
name: 组件名称 s.name = "XHNetwork"
version : 组件版本,和项目tag一致,install命令会根据这个版本号去下载指定tag版本的代码 s.version = "0.0.7"
summary : 摘要,长度一般比description短 s.summary = "XHNetwork"
description : 组件描述,文本长度必须比summary文本长度长 s.description = "A short description of XHNetwork lib"
homepage : 组件主页地址 s.homepage = "https://code.xhqb.io/appComponent/XHNetwork"
license : 授权协议,默认填写为MIT` s.license = "MIT" # s.license = { :type => "MIT", :file => "FILELICENSE" }
author : 作者、邮箱 s.author = { "赵正华" => "zhaozhenghua@xhqb.com" }
source : 项目git地址,tag值与s.verison版本一致 s.source = { :git => "https://code.xhqb.io/appComponent/XHNetwork.git", :tag => "#{s.version}" }
源文件 Classes文件夹必须放在根目录下才能被找到 s.sourcefiles = "Classes/.{h,m}" #spec.source_files = 'Classes//.{h,m}', 'MoreClasses/*/.{h,m}'
公有头文件 #s.publicheader_files = "Classes/*/.h"
匹配规则如下:
1.*匹配所有文件
2.c*匹配以名字C开头的文件
3.*c匹配以名字c结尾的文件
4.c匹配所有名字包含c的文件
5.**文件夹以及递归子文件夹
6.?任意一个字符(注意是一个字符)
7.[set] 匹配多个字符,支持取反
8.{p,q} 匹配名字包括p 或者 q的文件
图片及音频资源文件的加载方式 #spec.resource = 'Resources/HockeySDK.bundle' #spec.resources = ['Images/.png', 'Sounds/']
是否是ARC,默认true,如果不是,会自动添加-fno-objc-arc compiler flag s.requiresarc = true 支持的平台,如果不写默认支持所有平台,以下表示只支持ios平台,系统版本8.0以上 s.platform = :ios, "8.0"
依赖的系统的框架 s.frameworks = 'QuartzCore', 'CoreData'
如果在高版本的OS中调用新增的功能,并且在低版本的OS中依然能够运行,那么就要用到weakframeworks.如果引用的某些类或 者接口在低版本中并不支持,对于不支持的接口,可以在运行的时候判断,这样程序不会出错,如果不weak引用,程序在低版本下启动的时候就会崩溃掉 s.weakframework = 'MessageUI'
配置信息,根据个人需要填写 # s.xcconfig = { "HEADERSEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
依赖的第三方, 没有指定第三方依赖库,默认去下载最新的库版本 s.dependency 'XHAFNetworking'
四、私有组件配置用法
结尾
上面就是在小花钱包项目中进行 模块化/组件化 的搭架操作流程,希望这篇文章能对有同样需求的人有所帮助。如果各位在看了这篇文章之后还有什么疑问或者是发现有什么问题都可以在文后面留言。 共同进步,Best wishes!