内容简介:iOS的组件化,一直都是一个理念,很多大公司一直在强调却没有具体可行的或简单可行的方案。所以分享下大概思路。框架说明:大致的框架思路,其中会碰到一个颗粒度的问题,将颗粒度设定过大,则组件之间的耦合性过大,颗粒度设定过小,则将产生很多的组件和中间组件,组件的管理成本过大。(具体问题需要具体分析)
iOS的组件化,一直都是一个理念,很多大公司一直在强调却没有具体可行的或简单可行的方案。所以分享下大概思路。
框架说明:
- 继续集成:一个主工程(壳工程),包含所有的内容(整个项目),用于发包或打包测试。
- 基础组件: 不依赖其他任何组件,独立完成功能。主要有:*与业务无法的功能(如string或data的加密,category的封装) *对第三方库的封装(如AFNetworking,SDWebImage的封装)
- 业务公用组件:依赖基础组件或UIKit等系统组件,创建业务共同使用的功能(如分享,支付,网络访问)
- 中间组件:连接业务公用组件和业务组件,及业务组件之间的互相调用。(如Mediator的组件)
- 业务组件:单独的业务功能,不依赖其他业务组件。
大致的框架思路,其中会碰到一个颗粒度的问题,将颗粒度设定过大,则组件之间的耦合性过大,颗粒度设定过小,则将产生很多的组件和中间组件,组件的管理成本过大。(具体问题需要具体分析)
一、 Cocoapods的组件管理
1. pod spec文件创建
Pod::Spec.new do |spec| spec.name = 'Reachability' spec.version = '3.1.0' spec.license = { :type => 'BSD' } spec.homepage = 'https://github.com/tonymillion/Reachability' spec.authors = { 'Tony Million' => 'tonymillion@gmail.com' } spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.' spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' } spec.source_files = 'Reachability.{h,m}' spec.framework = 'SystemConfiguration' end 复制代码
根据内容编写项目的信息,小的细节可以学习Git上支持Cocoapods的项目,查看项目中*.spec文件。 如: (1). 添加资源文件使用 s.resource_bundles
(2). 需要添加多个文件,使用数组 s.source_files = ['ThirdSdk/Classes/**/*.{h,m}', 'ThirdSdk/Classes/**/**/*.{h,m}']
2. LICENSE和README.md文件
编写许可证和说明的文件。最好参考官方的写法,不然检测不过。
3.创建一个Example工程
关键一个Example的工程,在Podfile中采用直接引用Module文件进行组件的开发。 方便对单个组件进行调试 如 pod 'ThirdSdk', :path => '../'
可以直接对Module进行修改,添加,删除等。
4.本地资料库(cocoapods镜像)创建
新建一个Git库,取名Specs用来保存本地的所有私有库。 使用 pod repo add [name] [Git地址]
添加一个私有Cocoapods Specs镜像。 使用 pod repo push REPO [NAME.podspec]
将私有组件推送到私有第三方库镜像。
5.依赖第三方库
在Podfile文件中可以添加依赖的第三方库,包括Cocoapods和私有本地的库。
platform :ios, '7.0' source 'git@code.*.com:ios/Specs.git' source 'https://github.com/CocoaPods/Specs.git' target 'ThirdSdk_Example' do pod 'ThirdSdk', :path => '../' #cocoapods specs pod 'AliyunOSSiOS' #local specs pod 'WebService' end 复制代码
其中
source 'git@code.*.com:ios/Specs.git' source 'https://github.com/CocoaPods/Specs.git' pod 'AliyunOSSiOS' pod 'WebService'
二、组件之间的依赖
(1)对于基础组件的依赖,采用Pod 直接导致,在代码中进行import头文件。这个方式会导致基础组件的耦合性比较高。可以将组件的颗粒度设定的小一些,尽量抽取出不依赖其他组件的独立组件。再将这些独立的组件打包成一个较大的组件,方便管理。如Podfile中
#local specs pod 'Account' pod 'AppPod' pod 'WebService' 复制代码
其中的AppPod就是集合,包含很多独立的基础组件。
(2)如果是业务组件,在不同的业务之间,一定要避免组件间耦合,采用 Mediator
组件作为中间件,降低耦合。 具体可以参考[iOS应用架构谈 开篇]( casatwy.com/iosying-yon… ) 提供的Demo编写。
三、主工程
主工程(壳工程)引用所有的组件,并实现应用的工程。
iOS应用框架及Cocoapods内容的参考:
- casatwy.com/iosying-yon…
- www.cocoachina.com/ios/2016010…
- gracelancy.com/blog/2016/0…
- blog.csdn.net/xyxjn/artic…
- pingguohe.net/2015/11/24/…
- studentdeng.github.io/blog/2013/0…
- ishalou.com/blog/2012/1…
- stackoverflow.com/questions/2…
- www.cnblogs.com/Mr-ios/p/53…
补充
1. 使用pod install 更新失败的处理
在使用Cocoapods管理代码的时候,如果在GitHut上更新了代码,希望在project中执行pod install 来刷新代码,那么需要 删除Pods和Podfile.lock文件 然后在执行pod install 来刷新代码
使用pod update进行repo的更新
多次安装pod install 会出现Build Phase里多个Check Pods Manifest.lock的选项,这些选项可以删除。
删除这个目录下的缓存文件,进行第三方库文件的重新获取/Users/*/Library/Caches/CocoaPods/Pods/*
因为有可能因为版本号,没有增加,在Pods目录下的VERSION保存了这个版本的第三方库,那么将直接返回已经缓存的文件。所以当私有组件有代码修改后,则可以清空这个文件夹下的目录,来进行私有组件的更新。:+1::+1::+1:(研究了很久才发现这个终极解决方法)
2. Pod中生成文件夹形式或创建子组件
在*.podspec文件中,根据功能创建不同的子组件,如AFN中的
s.subspec 'Security' do |ss| ss.source_files = 'AFNetworking/AFSecurityPolicy.{h,m}' ss.public_header_files = 'AFNetworking/AFSecurityPolicy.h' ss.frameworks = 'Security' end 复制代码
生成的效果
这种方式也是 子组件 的方法,在pod中可以直接引用AFSecurityPolicy的组件,如 pod 'AFNetworking/Security'
此时仅仅引用的是Security组件,而不是整个AFN组件
在开发是看到的组件,文件夹会比较乱,当其他组件pod后,看到的文件夹就如AFNetworking一样的效果。
3. *.podspec的dependency使用
组件可以依赖其他的第三方库,如 s.dependency 'JTObjectMapping'
AFNetworking等。 同时也可以依赖私有的第三方库 : (1)使用 pod repo add [name] [Git地址]
添加一个私有Cocoapods Specs镜像。 (2)使用 pod repo push REPO [NAME.podspec]
将私有组件推送到私有第三方库镜像。 (3)在组件中就可以将已经上传的组件可以用来依赖了。
4. ThirdSdk组件
在ThirdSdk组件中,不能包含业务或项目相关的类,不然会导致互相依赖。仅仅包含第三方库的代码,可以降低耦合性。 如果能用Cocoapods管理的第三方库,尽量使用Cocoapods吧。
5. 加载静态库和framework
ss.vendored_frameworks = 'ThirdSdk/AlipaySDK/AlipaySDK.framework' ss.vendored_libraries = 'ThirdSdk/AlipaySDK/libcrypto.a', 'ThirdSdk/AlipaySDK/libssl.a' 复制代码
a文件不是一个source_files。
6. runtime不能返回Bool等基础数据类型
return [target performSelector:action withObject:params]; 复制代码
如果返回的值是Bool或其他的基础数据类型,那么将会 Crash 。
需要将返回值设置为NSObject对象类型或nil。
7. 组件中获取xib,png等resource时,bundle重新设置
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *bundlePath = [bundle pathForResource:@"StoreLocation" ofType:@"bundle"]; if (bundlePath) { bundle = [NSBundle bundleWithPath:bundlePath]; } 复制代码
其中StoreLocation是与podSpec中的s.resource_bundles里设置的保持一致。
s.resource_bundles = { 'StoreLocation' => ['StoreLocation/Assets/**/*', 'StoreLocation/Classes/Address/*.{xib}''] } 复制代码
8. 图片和URL的处理
1、每一个组件需要用到的图片,都放到组件的Assets文件夹中。 在iOS8及更高系统,组件中Xib访问image会从组件的Assets中读取。但是iOS7系统,Xib还是从 [NSBundle mainBundle]
的Assets中读取文件。 2、URL 不单独放到一个头文件中,放入组件的ViewModel中。
9. TAG的刷新
当有多人合作开发,TAG又一直维持在1.0.0时,那么需要每次更新所有的TAG。
需要选中“ 抓取并在本地存储所有标签”。
10. push 组件 *.podspec 文件
pod repo push Specs AppPod.podspec --allow-warnings 复制代码
推送时,如果一直报错,修护了Error还是一直报同样的Error,这时可以执行下 pod cache clean --all
清空缓存。
11. 不同configurations设置宏
当添加一个Ad-hoc的configuration,这个也需要设置DEBUG这个宏,并且在组件中也用到了DEBUG的宏定义,那么需要对所有的组件进行DEBUG的设置。方法如下
#设置Debug参数 post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| if config.name == 'Debug' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) DEBUG=1' end if config.name == 'Ad-hoc' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) DEBUG=1' end end end end #设置参数完成 复制代码
12. 更新OpenSSL失败
OpenSSL更新失败,可以删除/tmp/openssl 文件夹,重新尝试。
13. OpenSSL 的使用
在使用支付宝SDK时,会有引入OpenSSL文件夹,其中文件中使用 #include <openssl/e_os2.h>
。将SDK放入组件中,会报错,提示找不到文件。 解决方法: 在*.podspec文件中 添加 ss.header_dir = "openssl"
用来添加头文件夹openssl。
14. ARC 和 MRC 兼容
将使用MAC的放入subspec
s.subspec 'JTObjectMapping' do |ss| ss.source_files = 'StoreBase/Classes/JTObjectMapping/*.{h,m}' ss.public_header_files = 'StoreBase/Classes/JTObjectMapping/*.h' ss.requires_arc = false end 复制代码
因为JTObjectMapping第三方库使用的MRC所以特殊声明 ss.requires_arc = false
. 在主spec中使用的ARC,则声明 ss.requires_arc = true
. 此时主spec是ARC而JTObjectMapping是MRC,对JTObjectMapping中的文件都会添加一个-fno-objc-arc的编译宏。
15. 基础组件的版本更新
当主工程发布了版本,那么依赖的基础组件版本也固定,不能再做修改。当需要对基础组件进行修改,那么版本需要更新,版本号加一。 当某个基础组件A的版本号修改,那么依赖这个组件的所有组件BCD也都要修改版本。然后依赖BCD的组件EFG也要修改版本号,以此类推
16. 发布版本修改
发布版本修改:基础组件,将基础组件的所有依赖修改为大版本(如“=1.1.0”格式),必须指定版本号。比如有一个组件的版本号是1.0.5,那么这个版本进行了1.0.1到1.0.5的开发,在提交版本的需要修改1.1.0版本,并执行1.1.0版本。为了,(1)方便线上版本可以指定具体的版本。 (2)方便下一个版本的开发。 壳工程中,pod file文件的修改,将业务组件制定dev分支,修改为制定版本号,必须指定版本号。
业务组件的使用:开发时,podfile中直接dev分支获取代码,并在dev上进行开发。 等需要发布版本进行冒烟测试时,修改podfile为制定版本号。如“=1.1.0”。
pod 'Location', :git => 'git@code.xxx.com:ios/Location.git', :branch => 'dev' 复制代码
基础组件的使用在每个基础组件中,使用“~>1.0.3”进行开发,并在每次修改的时候,添加版本号。 基础组件依赖其他组件的时候,也修改为“~>1.0.3”, 那么在pod install的时候,就可以更新到最新的版本,不需要清理缓存。 发布版本的时候,在每一个组件中,指定版本号。如“=1.1.0”。保存每个发布的正式版本,都可以明确的知道所有组件的版本号。 发布版本后进行开发,那么需要修改依赖版本后“~>1.1.0”,不需要清理缓存,方便开发。 开发时,版本号的修改,仅仅针对需要修改的版本号。其他版本号保持不变。
图片资源创建一个图片资源的pod, 使用s.resources的方式进行添加图片。那么在xib中或imageNamed:"""直接可进行访问。不需要进行bundle的控制。:+1::+1::+1:
未完待续 // END
以上所述就是小编给大家介绍的《iOS的组件化思路分享》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 组件化之路—集成组件SDK
- Android组件化入门:一步步搭建组件化架构
- Android快速开发框架,基础库,样式库,组件化,组件集成
- Android组件化方案及组件消息总线modular-event实战
- 组件化实践
- 组件化架构漫谈
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Charlotte's Web
E. B. White / Puffin Classics / 2010-6-3 / GBP 6.99
This is the story of a little girl named Fern who loved a little pig named Wilbur and of Wilbur's dear friend, Charlotte A. Cavatica, a beautiful large grey spider. With the unlikely help of Templeton......一起来看看 《Charlotte's Web》 这本书的介绍吧!