IOS 工程架构 - 主流设计(1)
前言
一、常规项目
二、组件化的意义
三、cocoapods简单总结
关于工程架构,我认为没有最好的方式,只有根据项目场景采用最适合的方式。随着App的功能越来越复杂,业务模块越来越庞大,以及加入项目的成员越来越多。搭建一个优秀的架构是非常重要的。
由于我们公司的IOS团队人数比较少,(大概3-4人左右)以及项目并不是很庞大,所以我们目前的架构并没有像一些大厂团队那么的完善。
看过字节跳动团队发的一篇《抖音 iOS 工程架构演进》的同学应该都知道,他们的技术实力是相当厉害。而我们目前的架构可能就只停留在阶段二的过程中。
那么接下来我主要先针对目前主流的组件化模式做一个总结。
一、常规项目
我们一般的项目结构大概是这样子的(举一个之前项目的例子):

一个主工程+Pods。
主工程包含了所有的业务代码以及简单的基础层代码,和所有的资源文件。
Pods里面是一些第三方的库。
显然这样的项目基本上是没有什么架构而言的。但是对于一个比较小的项目,或者是外包项目,已经可以完全满足我们的需求了。但是对于公司项目的不断升级,版本不断的迭代,显然这种模式会将主工程的代码堆积的越来越大,造成多人开发的时候非常不利于协作和代码架构不清晰的问题。从而造成开发效率下降。
那么接下来,我们先来总结一下常用的组件化开发的框架。
二、组件化的意义
对于上面说的常规项目,如果是小的外包项目等功能比较小的项目,我们根本不用去做组件化。
那么我在什么样的需求下需要做组件化呢?我简单的总结为3个条件。
1、项目比较大,模块之间的耦合比较大。
2、团队的规模比较大,基本上最少3人以上。(当然1、2个人也可以简单的玩一玩)
3、模块的重用性比较大。可能被多个模块引用。
三、cocoapods简单总结
#pod install --verbose --no-repo-update
Cocoapods 从1.8版本开始,将默认源切换到了CDN服务,也就是不再将整个的repo master先下载下来才能正常使用pods,而是用按需下载。
因此:pod install 和 pod update 速度都很快
trunk
- Type: CDN
- URL: https://cdn.cocoapods.org/
- Path: /Users/magic-geng/.cocoapods/repos/trunk
如果使用trunk时,发生了超时
(1)可以绑定host(网上搜索一堆解决方案)
(2)挂代理
(3)指定 source 'https://github.com/CocoaPods/Specs.git' 为master(实在不行就指定源来解决吧)。
公有仓库流程
以AFNetworking为例,以下简称AF。
我们在用到AF时,会在podfile里面写:
source 'https://github.com/CocoaPods/Specs.git'
pod 'AFNetworking','~> 4.0.0'
那么source指向的是源路径。
Cocoapods source 这个地址是个公共仓库,里边存储各个第三方的podspec文件,这个podspec文件中记录有各自第三方库的仓库地址。
比如AF,在github上仓库地址是这个AFNetworking source,其中包含对应的podspec文件,这个文件中有存储AFNetworking source这个地址,并且Cocoapods source 中有存储有这个文件。
那么当我们在使用pod 'AFNetworking','~> 4.0.0'的时候,cocoapods会去Cocoapods source 中查找AFNetworking对应的podspec文件,找到后从中取出AFNetworking source这个地址,然后里边就是我们要的第三方库的源码了。
关于发布公有仓库,以后我们再具体分析。
私有仓库流程
做为组件化开发,我们并不想把我们的每一个组件都公开化,那么我们需要只用私有仓库。
以一个(DDSThirdLib)模块为例:
1、我们先在代码托管平台创建一个私有仓库,这里我使用的是码云。比如生成的仓库地址为 https://gitee.com/xxx/ddsthird-pod.git。
2、通过pod lib create DDSThirdLib 创建模版测试工程。同时修改DDSThirdLib.podspec文件。
3、通过pod lib lint --verbose,检测异常,通过检测之后,将模版工程上传到远程的代码仓库。
在这一步中,如果遇到这个错误
4、pod lib lint --verbose --sources='https://gitee.com/zykjapp/ddsspecs.git,https://github.com/CocoaPods/Specs.git'
The following build commands failed:
Ld /Users/magic-geng/Library/Developer/Xcode/DerivedData/App-ahnctoxlgvckpaewnsruhiktppyk/Build/Intermediates.noindex/App.build/Release-iphonesimulator/App.build/Objects-normal/arm64/Binary/App normal arm64
原因是指令集问题,可以加入
s.pod_target_xcconfig = { 'VALID_ARCHS' => 'x86_64 armv7 arm64' }
4、此时我们可以通过 pod 'DDSThirdLib', :git=>'https://gitee.com/xxx/DDSThirdLib.git' 来下载我们的库。
5、第4个显然不是很方便。所以我们应该创建私有仓库索引仓库。
我们在码云上创建一个自己的远程私有索引库,用来存放私有框架的详细描述信息,即podspec文件。 地址为 https://gitee.com/xxx/ddsspecs.git
6、添加我们自己的索引仓库
pod repo add DDSSpecs https://gitee.com/xxx/ddsspecs.git
通过pod repo list 查看

DDSSpecs已经添加了。
7、进入我们的私有库目录,首先通过git,打一个tag上传,然后将我们组件库的.podspec上传到我们的索引仓库。
pod repo push DDSSpecs DDSThirdLib.podspec
8、当我们每次修改私有库之后,都要先打一个tag(同时在.podspec指定新版本号),然后再执行pod repo push DDSSpecs DDSThirdLib.podspec。
pod repo push DDSSpecs DDSBaseLib.podspec --sources=https://gitee.com/zykjapp/ddsspecs.git,https://github.com/CocoaPods/Specs.git
9、在使用我们的私有仓库时,需要在podfile中指定source
use_frameworks!
#source 'https://github.com/CocoaPods/Specs.git'
source 'https://gitee.com/zykjapp/ddsspecs.git'
platform :ios, '10.0'
target 'DDSBaseLib_Example' do
pod 'DDSBaseLib', :path => '../'
# pod 'DDSThirdLib', :git=>'https://gitee.com/shanguang_app/ddsthird-pod.git'
pod 'DDSThirdLib', '~> 0.2.0'
target 'DDSBaseLib_Tests' do
inherit! :search_paths
end
end
删除搜索索引,rm ~/Library/Caches/CocoaPods/search_index.json,再pod search
10、如果把第三方的framework直接拖入到私有库。
那么配置如下:
//设置支持的指令集
valid_archs = ['arm64','x86_64','armv7']
s.xcconfig = {
'VALID_ARCHS' => valid_archs.join(' '),
}
//framework路径
s.vendored_frameworks = 'DDSFaceULocal/Classes/libCNamaSDK.xcframework'
//资源路径
s.resource_bundles = {
'DDSFaceULocal' => ['DDSFaceULocal/Assets/*/*']
}