CocoaPods
CocoaPods是Swift和Objective-C Cocoa项目的依赖管理器。使用它可以方便地导入三方库,并导入库的依赖,免去了手动完成三方库导入配置。除了导入,还可以利用CocoaPods搭建你自己的私有库体系。类似于 Java 的 Maven,nodejs 的 npm。
CocoaPods是使用Ruby构建的,所以需要在本地准备好Ruby环境。不过Mac默认已经有了Ruby环境,可以免去搭建Ruby环境了,但是还需要进行简单配置。
安装
为了提高速度,需要更换RubyGems源,这里换成国内的镜像源(http://gems.ruby-china.com/)。首先查看当前的源:
gem sources -l
移除当前源,并添加新的源
gem sources --add http://gems.ruby-china.com/ --remove https://rubygems.org/
再次查看当前源,确认是否更换成功。
接下来安装 CocoaPods:
sudo gem install cocoapods
# 如果是Mac OS X 10.11 以后的版本,使用以下命令
sudo gem install -n /usr/local/bin cocoapods
PS:如果需要卸载,可以执行sudo gem uninstall cocoapods命令。
然后执行pod --version验证是否安装成功。
最后,我们还需要进行本地环境设置,这需要执行pod setup命令,即将官方的Specs repo 拉到本地,其本地存放路径是 ~/.cocoapods/repos/master。注意,这一步使用的是GitHub仓库,由于GitHub在国内访问极为缓慢,不推荐直接使用,我们可以使用码云的镜像替代,访问速度更快。因此建议先切换到国内的镜像仓库,然后再执行pod setup命令。
要使用码云的同步镜像,需要进行以下镜像更换操作:
pod repo remove master
pod repo add master https://gitee.com/mirrors/CocoaPods-Specs.git
到此,我们成功完成了CocoaPods环境安装。
使用
创建Podfile
先cd到工程目录下,然后执行命令新建Podfile:
pod init
引入依赖
当我们想要使用CocoaPods管理依赖库时,首先应在CocoaPods仓库检索以确定是否包含该依赖库。可以使用pod search来检索依赖库的名称:
pod search AFNetworking
当检索到相关库的信息后,就可以打开Podfile文件配置依赖。
pod 'AFNetworking'
# 或者配置版本
pod 'AFNetworking', '~>3.2.1'
如果pod install太慢,可以跳过更新repo。
pod install --verbose --no-repo-update
其他命令:
pod outdated:列出当前所有库的最新版本pod update:如果没有指定版本,则会更新到最新的版本。会忽略Podfile.lock中已锁定的版本pod lib create仓库名:在本地创建一个基于pod模板的git仓库pod lib lint:验证本地pod库pod spec lint:验证远程pod库
Xcode 工程结构
Schema、Target、Project 和 Workspace 是组成一个 Xcode 工程最核心的单元。
Target :是工程中的最小可编译单元,每一个 target 对应一个编译输出,这个输出可以是一个链接库,一个可执行文件或者一个资源包。它定义了这个输出被 build 的所有细节。在 Build Settings,Build Phases 中配置的各种选项,大部分都是对应到指定的 target 的
Project :表示一个 Xcode 工程。它是管理资源的容器,本身是无法被编译的,所以每个 project 至少应该有一个可编译的 target。它管理工程下的 target 集合以及它们的源码,引用的资源,framework 等等。在多数情况下,工程就是一个 project,可以在 finder 中双击
.xcodeproj文件打开。Workspace:当一个 target 被多个不同的项目依赖,或者 project 之间互相引用,那么我们就需要把这些 project 放到相同的目录中管理。管理相同层级 project 的容器就是 Workspace。它是纯粹的容器,不参与任何编译链接过程。在 iOS 开发中,常使用 Cocoapods 来管理三方库,它会把这些三方库的源码组装成一个 project,然后和主工程的project一起放入到 workspace 中,并自动配置好主工程与 pods 库之间的依赖。所以如果引入了 Cocoapods,就必须打开 workspace 才能正常编译。我们可以双击
.xcworkspace文件来打开workspaceScheme:针对一个指定的 target,scheme 定义了构建这个 target 时使用的配置选项,执行的任务,环境参数等等。Scheme 可以理解为一个工作流。当我们编译时,Xcode 会按照 scheme 中的定义,去执行对应的工作流。
Scheme 中预设了六个主要的工作流: Build, Run, Test, Profile, Analyze, Archive。其中最重要的一个配置是选择 target 的 build configuration,对每一个 project,会有两个默认的 build configuration:debug 和 release。
原理简述
CocoaPods 将所管理的 Pod 依赖库组装成一个个 Target,统一放入 Pods project 中的 Demo target,并自动配置好 Target 间的依赖关系。之后将 Example 主工程和 Pods 工程一起打包到新建的 Example.workspace,配好主工程与 Pods 工程之间的依赖,完成最终转换。

Pods项目最终会编译成一个名为libPods.a的文件, 主项目只要依赖这个.a文件即可。
Podfile
是开发者用来配置依赖的配置文件,相当于Flutter中的pubspec.yaml
常用配置说明:
source- 指定 specs 的位置,自定义添加自己的 podspec。
- 如果没有自定义添加 podspec,则可以不添加这一项,因为默认使用 CocoaPods 官方的 source。一旦指定了其它 source,那么就必须指定官方的 source,如上例所示。
platform :iOS, '8.0'指定开源库应该被编译到哪个平台以及平台的最低版本。use_frameworks!使用动态 frameworks 替换静态链接。Swift 项目默认use_frameworks!;OC 项目默认#use_frameworks!inhibit_all_warnings!屏蔽 CocoaPods 库里面的所有警告。也可在子 target 里定义,如果想单独屏蔽某 pod 库的警告:pod 'JYCarousel', :inhibit_warnings => trueworkspace指定包含所有 projects 的 Xcode workspace。若没指定workspace,且 Podfile 所在目录下只有一个 project,那么 project 的名称会被用作workspace的名称target 'xxxx' do ... end指定特定 target 的依赖库;还可以嵌套子 target 的依赖库
配置依赖库的语法:
pod 'AFNetworking' --> 不指定依赖库版本,表示每次都获取最新版本
pod 'AFNetworking', '2.0' --> 只使用 2.0 版本
pod 'AFNetworking', '> 2.0' --> 使用高于 2.0 的版本
pod 'AFNetworking', '>= 2.0' --> 使用大于或等于 2.0 的版本
pod 'AFNetworking', '< 2.0' --> 使用小于 2.0 的版本
pod 'AFNetworking', '<= 2.0' --> 使用小于或等于 2.0 的版本
pod 'AFNetworking', '~> 0.1.2' --> 使用大于等于 0.1.2 但小于 0.2 的版本
pod 'AFNetworking', '~> 0.1' --> 使用大于等于 0.1 但小于 1.0 的版本
Podfile.lock
此文件是我们新建Podfile文件后会自动生成的一个文件,里面保存了已安装的依赖库的版本。
当我们第一次运行pod install时,如果对依赖库不指定版本号,cocoapods就会安装最新版本,同时将该库版本记录在Podfile.lock文件中。这个文件会保持对每个依赖的pod库版本的跟踪,并且锁定这些版本。再执行pod install的时候,只会处理没有记录在Podfile.lock中的依赖库。因此,为了保证团队内成员的依赖库版本一致,该文件应该加入到Git中管理。注意,只有执行 pod update 时才会更改 Podfile.lock文件。
Podspec
Podspec 是用于描述一个 Pod 库的源码和资源将如何被打包编译成库或 framework 的配置文件。换句话说,如果我们想自己创建一个Pod库,那么就需要学习Podspec 配置。
Pod::Spec.new do |spec|
spec.name = 'MyLib'
spec.version = '0.1.0'
spec.license = { :type => 'MIT' ,:file => 'LICENSE'}
spec.homepage = 'https://github.com/arcticfox1919/MyLib'
spec.authors = { 'arcticfox' => 'arcticfox1919@163.com' }
spec.summary = 'Some Class for iOS and OS X.'
spec.source = { :git => 'https://github.com/arcticfox1919/MyLib.git', :tag => "v#{spec.version}" }
spec.source_files = 'MyLib/Classes/**/*'
end
几个需要注意的配置:
添加依赖
# 依赖的系统frameworks
spec.frameworks = 'AVFoundation', 'CoreGraphics', 'Security'
# 依赖的三方framework
spec.dependency "MBProgressHUD"
spec.dependency "AFNetworking", "~> 3.0"
# 依赖的系统库
spec.libraries = 'c++', 'sqlite3','iconv'
添加本地项
# 添加本地frameworks库(非系统)
spec.vendored_frameworks = "xxx.framework"
# 添加依赖的静态库(非系统)
spec.vendored_libraries = 'xx/libxxx.a'
# 添加源文件
spec.source_files = "xxx/**/*"
spec.source_files = 'Classes/*.{h,m}'
# 添加公共头文件
spec.public_header_files = 'Classes/*.h'
# 添加本地资源
spec.resources = "xxx.bundle"
创建自己的Pod库
# 创建Pod库
pod lib create MyLib
# 检查podspec配置
pod lib lint MyLib.podspec
除此外,我们也可以直接进入一个现有的代码文件夹,执行pod spec create MyLib来生成一个Podspec文件
依赖本地Pod库
在Podfile中添加本地依赖配置
pod 'MyLib', :path => '../MyLib'
发布Pod库
如果我们想将自己的库发布到CocoaPods 远程仓库,那么我们编写的库代码应该被托管到GitHub(或其他Git服务器)上,然后为给代码打上版本Tag,接下来将 spec.source配置指向这个Git仓库地址。
git tag 0.1.0
执行pod trunk me查看我们是否创建了CocoaPods 帐号,如果没有,则应当先注册一个帐号:
# 邮箱 + 用户名
pod trunk register example@example.com 'zhangsan'
最后执行pod spec lint MyLib.podspec --verbose检查库,检查无误,执行pod trunk push MyLib.podspec推送到远程。
公众号“编程之路从0到1”
