iOS开发之ios组件化怎么实现?
随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助cocoapods版本管理工具对原有应用工程进行拆分。但是仅仅完成代码拆分还不足以解决业务之间的代码耦合,为了更好的让拆分出去的业务工程能够独立运行,必须进行拆分并且实现组件服务化。
1.组件和组件之间没有明确的约束。
2.组件单独开发、单独测试,不能揉入主项目中开发,测试也可以针对性的测试。
由于本人的习惯,喜欢把很复杂的问题大白话化。组件是什么?它就是通过cocoapods来管理的几个文件,它能实现特定的功能。通常它都采用的私有库和私有源,不然大伙都可以看到你的代码。当然也有的组件本来就是为了开源的,开源的库通常放在公有源上。
组件化主要为了解决不同app代码重复性问题,便于维护,其次为了代码功能清晰。当组件更新,各个app只需要执行pod update就把组件的功能代码更新了,不用每个app重新导入或修改相同的代码了。新建app只需要配置podfile文件,执行pod update命令就能把组件导入过来大大提高了开发效率。每个组件实现特定的功能,不用在一堆业务代码中翻找不同的功能代码了,你说代码功能能不清晰吗?
组件主要分三类:
基础功能组件:(类似于性能统计、networking、网络诊断、定制categories安全处理扩展类组件等)
按功能分库,不涉及产品业务需求,跟库library类似
通过良好的接口拱上层业务组件调用;
不写入产品定制逻辑,通过扩展接口完成定制;
基础ui组件:(例如下拉刷新组件、弹出框组件、小菊花组件、选择框组件等)
产品内通用ui组件;(各个业务模块依赖使用,但需要保持好定制扩展的设计)
公共通用ui组件;(不涉及具体产品的视觉设计, 目前较少)
产品业务组件:(例如支付组件、分享组件、页面管理组件、评价组件、版本更新组件、websocket等长连接组件)
业务功能间相对独立,相互间没有model共享的依赖;
业务之间的页面调用只能通过uibus进行跳转;
业务之间的逻辑action调用只能通过服务提供;
网络组件可以只包含对afnetworking的进一步抽象,以便于更简单的使用。它比使用扩展类写在一个文件里的可读性要强的多。几个相关的请求在一个类文件里比所有的请求都在一个类文件里,大家想像就知道那个更合理。
本文主要的内容是组件化的实现,不是讲组件化的代码具体实现的,关于组件化代码实现以后再说。
你可以这样理解,就是想把几个.h和.m等文件怎么用cocoapods把它变成私有库,指定的成员可以下载。大公司都是自己搭建的gitlab服务器。小公司大都使用的是git服务器。当然自己搭建的服务器上传下载要比git服务器要快的多。本文主要以git服务器为示例,所有*需要你换成自己的路径和文件,工程名。
以前在大公司都是比人专门建立了私有源和环境,自己上传组件就可以。当了新公司要当拓荒者一个人实现组件化,遇到问题不是一般的大,一个很小的问题就卡了我两周。从零开始组件化你才能充分理解组件化的重要和本质。
下面是实现组件化的步骤。
1. 你首先要安装cocoapods。网上一抓一大把,你慢慢学习去吧!不过我遇到一个奇靶的问题。我以前装cocoapods装了一半失败了,以后怎么装也装不成功。后来把它卸载了再装才成功。
2. 在git服务器上建立你自己私有源,就是存放podspec文件的地方。注意:创建时一定要勾选initialize this repository with a readme前面勾选。我就是开始忘记忘记勾选这个选型,上传了两周私有源全部失败。空工程无法使用pod repo push推送本地私有源到远程私有源。若忘记了,你可以删除这个私有源再重新创建并勾选这个选项。当然若因为各种原因不能删除,那么你就用git卸载工程到本地,给它传一个说明文件吧!当然你也可以用命令创建。
echo “# tencentbugly” >> readme.md
git init
git add readme.md
git commit -m “first commit”
git remote add origin https://github.com/**/tencentbugly.git
git push -u origin master
这个tencentbugly是你要创建的私有源的名字,你修改成你自己的私有源的名称就可以。
3. 创建本地私有源。
pod repo add yixiangspec https://github.com//.git
4. 在git服务器上建立你自己私有代码库,下载到本地,通常在本地需要建立一个工程,这个工程的主要目的是检查是否代码是否能编译和运行,当然也可以包含对该模块的测试代码。增加*.podspec。注意:配置文件中不能有中文标点符号,或者会编译不通过。
5. 上传代码到私有库地址,并且打标签,注意一定要勾选推送标签:origin 。
一般一个指定组件都是一个人维护,所以一般都是指直接推送到master主分支。
6. 在*.podspec所在文件路径下执行代码检查,告警一般可以忽略(–allow-warnings)。例如:pod spec lint modulemanager.podspec –allow-warnings –use-libraries
注意:若是本组件需要访问私有源和公有源都需要加上。例如:pod spec lint yxrequestmanager.podspec –sources=’https://github.com//.git,https://github.com/cocoapods/specs.git’ –allow-warnings
编译成功的例子:
podspec –allow-warnings –use-libraries
-> modulemanager (0.0.1)
analyzed 1 podspec.
modulemanager.podspec passed validation.
7. 编译检查通过,推送到私有源。例如:pod repo push * modulemanager.podspec –allow-warnings
注意:若是本组件需要访问私有源和公有源都需要加上。例如:pod repo push yixiangspec yxpaymanager.podspec –sources=’https://github.com//.git,https://github.com/cocoapods/specs.git’ –allow-warnings –use-libraries
若你的组件有几百兆(如通信基础组件),可能需要很常时间,毕竟git服务器在国外,大家耐心等待吧!
上传成功的例子
jiaguoshangdemacbook-air:modulemanager jiaguoshang$ pod repo push * modulemanager.podspec –allow-warnings
validating spec
-> modulemanager (0.0.2)
updating the `*’ repo
already up to date.
adding the spec to the `*’ repo
[add] modulemanager (0.0.2)pushing the `yixiangspec’ repo
8. 在项目所在文件夹修改或创建podfile文件,增加你的组件。
下面是包含私有源和公有源的podfile文件例子:
uncomment this line to define a global platform for your project
source ‘https://github.com/enjoyor-runlu/*.git’
source ‘https://github.com/cocoapods/specs.git’
platform :ios, “8.0”
target ‘artenjoymentwechatauction’ do
# uncomment this line if you’re using swift or would like to use dynamic frameworks
# use_frameworks!
# pods for *
pod ‘yxfdcategories’
##################################第三方###########################
#yymodel–数组转模型组件
pod ‘yymodel’, ‘1.0.4’
#yycategories–给类添加的分类
pod ‘yycategories’, ‘1.0.4’
#内存泄漏检测,正式环境需要注释下面一行
pod ‘mleaksfinder’,’0.2.1’
end
下面是一个简单的一个只包含classes文件夹下的.h和.m文件的组件管理组件的配置文件(modulemanager.podspec):
#
any lines starting with a # are optional, but their use is encouraged
to learn more about a podspec see https://guides.cocoapods.org/syntax/podspec.html
#
pod::spec.new do |s|
s.name = ‘modulemanager’
s.version = ‘0.0.2’
s.summary = ‘modulemanager.’
this description is used to generate tags and improve search results.
* think: what does it do why did you write it what is the focus
* try to keep it short, snappy and to the point.
* write the description between the desc delimiters below.
* finally, don’t worry about the indent, cocoapods strips it!
s.description = <<-desc
todo: add long description of the pod here.
desc
s.homepage = ‘https://www.baidu.com/’
# s.screenshots = ‘www.example.com/screenshots_1’, ‘www.example.com/screenshots_2’
s.license = { :type => ‘mit’, :file => ‘license’ }
s.author = { ‘jiaguoshang’ => ‘*@163.com’ }
s.source = { :git => ‘https://github.com/*/modulemanager.git’, :tag => s.version.to_s }
# s.social_media_url = ‘https://twitter.com/’
s.ios.deployment_target = ‘8.0’
s.source_files = ‘modulemanager/classes/*.{h,m}’
s.source_files = “modulemanager”, “‘modulemanager/*/.{h,m}”
# s.resource_bundles = {
# ‘modulemanager’ => [‘modulemanager/assets/*.png’]
# }
# s.public_header_files = ‘pod/classes/*/.h’
s.frameworks = ‘uikit’, ‘foundation’
# s.dependency ‘afnetworking’, ‘~> 2.3’
end
下面是一个既依赖私有库又依赖公有库的配置文件(yxrequestmanager.podspec):
#
be sure to run `pod lib lint yxrequestmanager.podspec’ to ensure this is a
valid spec before submitting.
#
any lines starting with a # are optional, but their use is encouraged
to learn more about a podspec see https://guides.cocoapods.org/syntax/podspec.html
#
pod::spec.new do |s|
s.name = ‘yxrequestmanager’
s.version = ‘1.1.9’
s.summary = ‘yxrequestmanager.’
this description is used to generate tags and improve search results.
* think: what does it do why did you write it what is the focus
* try to keep it short, snappy and to the point.
* write the description between the desc delimiters below.
* finally, don’t worry about the indent, cocoapods strips it!
s.description = <<-desc
todo: add long description of the pod here.
desc
s.homepage = ‘https://www.baidu.com/’
# s.screenshots = ‘www.example.com/screenshots_1’, ‘www.example.com/screenshots_2’
s.license = { :type => ‘mit’, :file => ‘license’ }
s.author = { ‘jiaguoshang’ => ‘*@163.com’ }
s.source = { :git => ‘https://github.com/enjoyor-runlu/yxrequestmanager.git‘, :tag => s.version.to_s }
# s.social_media_url = ‘https://twitter.com/’
s.ios.deployment_target = ‘8.0’
s.source_files = ‘yxrequestmanager/classes/*/.{h,m}’
s.source_files = ‘yxcache’, ‘yxrequestmanager/classes/yxcache/*.{h,m}’,
s.source_files = ‘aescategory’, ‘yxrequestmanager/classes/aescategory/*.{h,m}’
s.source_files = ‘yxrequest’, ‘yxrequestmanager/classes/yxrequest/*.{h,m}’
s.source_files = “yxrequestmanager”, “yxrequestmanager/*/.{h,m}”
s.resource_bundles = {
‘yxrequestmanager’ => [‘yxrequestmanager/classes/*.xcassets’]
}
# s.public_header_files = ‘pod/classes/*/.h’
s.frameworks = ‘uikit’, ‘foundation’
s.dependency ‘yxfdcategories’
s.dependency ‘afnetworking’, ‘3.1.0’
s.dependency ‘tmcache’
end