iOS 必备工具 - CocoaPods


第一部分:CocoaPods 的使用


需求

在 iOS 开发过程中,当你需要使用必要的三方库时,是否被各种库搞得筋疲力尽?
当你需要使用三方库时,你不仅需要手动下载库,还需要为该库添加可能依赖的系统库;在库需要更新时,你依然需要重复上述操作,并且当你想要删除一些不再需要的三方库时,你还需要连同依赖的系统一并删除,删除的过程中特别注意其他库所依赖的部分。总之,手动管理库的过程相当的繁琐而又容易出错。那么,有没有相关的工具帮我们完成这些繁琐的是呢?这就要提到 iOS 程序员需要掌握的必备工具 - CoCoaPods。无论你是新手还是老手,这工具都是接下来经常打交道的,所以,这里推荐新手们快速的掌握该工具的使用,因为它能帮你省去相当多的麻烦。

CocoaPods简介

CocoaPods 是库管理工具,iOS 开发过程中会遇到两个头疼的问题 – 依赖库的重复性和三方库的更新,使用 CocoaPods 管理工具帮你自动完成上述工作,而你所需要做的事情就是编写一份文件,来指定需要的三方库以及版本等信息,然后一句更新命令即可。另外绝大部分有名的开源库,都支持了 CocoaPods,这也让 iOS 开发人员避不开使用 CocoPods。当然你也可以发布自己的库到 CocoaPods 上,分享你的工具。

想要了解更多的信息,可以查阅 官方指导文档

安装 CocoaPods

安装 CocoaPods 需要 Ruby 环境,幸运的是,OS X 系统默认安装了 Ruby 环境,你可以使用下面的命令来查看当前的 Ruby 版本。

$ ruby -v 

CocoaPods 要求 Ruby 一定版本的,一般大于 2.2.0 即可,如果还不行,选择更高的版本即可。如果你的 Mac 达到了要求,那么使用下面的命令安装即可。

$ gem install cocoapods

如果你的账号在电脑上没有权限,使用下面命令,并输入电脑的密码。

$ sudo gem install cocoapods

如果顺利安装完成,执行以下命令来进行初始化,它会下载服务器中所有的框架信息,缓存到电脑本地。过程可能需要较长时间。

$ pod setup

如果顺利,你就可以跳到使用 CocoaPods 使用步骤。

安装过程中可能出现的问题
  • 执行 gem install cocoapods 没反应

因为 Ruby 默认的来源是 https://rubygems.org/ , 国内访问时如果没有梯子时会非常困难,可以将源替换为国内的镜像服务器。

执行下面命令查看当前使用的源。

$ gem sources -l

将源替换为国内镜像服务器的源。先删除再添加。

$ gem sources --remove https://rubygems.org/
$ gem sources -a https://gems.ruby-china.com/
  • Ruby 版本过低

当出现提示 active support requires Ruby version >=2.2.0 字样时,你需要将电脑上 Ruby 环境的版本升级到 2.2 以上。关于升级 Ruby,你可以使用 RVM(Ruby Version Manager,Ruby版本管理器)。

$ curl -L get.rvm.io | bash -s stable
$ source ~/.bashrc
$ source ~/.bash_profile

升级 Ruby

列出当前可以使用的各个版本信息。

$ rvm list known rubies

安装对应的版本

$ rvm install x.x.x

更多的问题,请自行搜索网络最新文章。

使用 CocoaPods 管理三方库

我们先新建一个演示工程:cocoapodsDemo。

在终端使用 cd 命令进入到该项目下,执行下面命令来创建三方库的配置文件 Podfile。你也可以手动创建,但是名称必须为 Podfile

$ pod init

使用 vim Podfile 命令进入该文件,或者直接在项目结构中查看。
项目结构中的Podfile文件
编辑 Podfile 文件,以 AFNetworkingJSONKitReachability为例,编辑后的内容如下:
编辑Podfile文件
Podfile更多的语法

编辑完成保存并退出,终端进入到该项目目录下,使用下述命令完成三方库的安装。

进入到项目目录。

 $ cd desktop/cocoapodsDemo

执行 CocoaPods 安装命令。

$ pod install

出现以下提示,表示成功安装。
成功安装三方库
注意,安装完成之后,当前项目 Project 不能正常运行了,我们需要使用 CocoaPods 为我们创建的 workspace 来运行项目。我们重新打开项目目录。
安装后的目录
对比最初的目录结构,这里已经多出了四个文件,其中:

  • Podfile 是三方库的配置文件
  • xxx.xcworkspace 是管理我们项目和所有依赖库的 workspace
  • Podfile.lock 是执行安装后的信息
  • Pods 存放了三方库文件以及系统依赖库

我们打开这里的 xxx.xcworkspace。项目结构如下:
workspace的目录结构
以后你就可以通过 xxx.xcworkspace 来运行你的项目了,其他关于三方库的部分都交给 CocoaPods 来管理吧。

Cocoapods 帮你做了什么呢?

打开 cocoapodsDemo 项目的 Frameworks ,你可以找到一个 libPods-xxx.a 文件。
编译的 .a 文件
CocoaPods 通过文件 Podfile 中的三方库信息下载你所需要的库,并将这些库编译成一个 .a 的静态库链接到你的项目,除此之外,CocoaPods 帮你完成依赖库的管理,它能够去除三方库的依赖库的重复库,在你删除不需要的三方库是,同样自动删除多余的依赖库。

CocoaPods 将所有的第三方库以 target 的方式组成一个名为Pods的工程里,我们的工程和第三方库所在的工程 Pods 由一个新生成的 workspace 管理。

workspace的组成

更多常用的 pod 命令
  • 新增或删除三方库

Podfile 新增或删除指定三方库的配置信息。重新执行下面命令。

$ pod install
  • 搜索三方库的信息

你可以使用 search 搜索一些三方库的信息,你无需全匹配,模糊搜索即可。

$ pod search AFNetworking
$ pod search SDWeb

注:search 命令只会使用本地所创建的索引进行搜索,因此,你搜索到的最新库可能并不是最新版本。

  • 更新框架 / 更新本地索引文件

当你的 Podfile 文件中没有为三方库指定特定版本,但后续又想将三方库更新到最新,你可以使用 update 命令来更新本地索引并完成类似 install 的安装效果。

# 同步远程最新信息
$ pod update
# 只根据本地缓存更新到最新的版本
$ pod update --no-repo-update
  • 更新指定库

有时候你可能并不需要更新所有的三方库,这种情况经常出现,例如你的 Podfile 文件中只有部分库指定了版本,你这时候使用 update 命令,默认是会将所有未指定的三方库都进行了更新,如果三方库出现 api 更新或替换,你的项目将出现错误问题。又或者你的网络不稳定,你只想更新一个或指定的几个库,你需要下面的命令来进行指定库的更新。

$ pod update 三方库  --verbose --no-repo-update
  • 本地索引库在哪里?

通过 shift + command + G 打开前往文件夹,输入

~/.cocoapods/repos/

找到 master/specs 文件夹,该文件夹下缓存了 CocoaPods 的所有的三方库信息,有三层文件夹,分别是 0-f ,随便点开某个三方库的索引文件,你可以在这里看到该三方库的历史版本。

某个库的索引文件
其中,文件 xxxx.podspec.json 中就是三方库的更详细的信息,例如作者,当前版本,介绍,目录结构,依赖库等等。

xxx.podspec.json
由于 CocoaPods 在时刻更新,所以你的缓存并非最新,所以你可能需要更新本地的 repos 。使用下面命令来更新。

$ pod repo update

该命令会同步所有库的最新本版信息,如果你只想关心指定的库,你可以使用下面命令。

pod repo update ~/.cocoapods/repos/***/库名

如果指定更新依旧无法更新,但是你急需使用最新的库,你可以去官网git手动去下载对应的库,也可以从有的同事小伙伴那边直接复制。

  • 更多相关的命令

cocoapods的命令资料


第二部分:让自己的库支持 CocoaPods

需求

我们想要将自己开发的工具组件给他人使用,通常将共享文件封装成 framework,让别人手动导入到自己的项目中去,这也是开放平台的通常做法。除此之外,我们还可以通过 Cocoapods 来分享自己的工具组件,就像 AFNetworkingSDWebImage 一样。

必要条件

  1. 项目代码库(如 git、码云等)并发布了release。
  2. podspec 配置文件
  3. cocoapods 账号

如果你已经有了 Git 仓库,你只需要在项目中创建并配置你的项目信息即可,文件名为 yourProjectName.podspec 。该文件语法可以看 官网指导

其他部分你可以参考这篇文章 iOS 让自己的框架支持cocoapods

接下来的篇幅,主要介绍的是从无到有的过程,这部分的内容节选自 iOS 组件化 中的内容。关于组件化你可以通过上面的链接来了解更多。

我们来创建一个关于网络请求的功能组件 LLNetworking

  • 拉取模版

我们将创建在桌面上的一个名为 Demo 文件夹。通过终端进入到该文件夹下,然后输入命令:

$ pod lib create LLNetworking

这个命令会为了拉取 Pod 的 基础模板。拉取之后,还会通过询问的形式为你配置一些东西:

// 作用的平台
What platform do you want to use?? [ iOS / macOS ]
 > iOS

// 语言环境
What language do you want to use?? [ Swift / ObjC ]
 > ObjC

// 是否需要一个 demo 用来测试组件
Would you like to include a demo application with your library? [ Yes / No ]
 > Yes

Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > None

Would you like to do view based testing? [ Yes / No ]
 > Yes

// 组件中,文件的前缀
What is your class prefix?
 > LL

确认之后,系统会为你自动配置项目,创建好的项目如下:

LLNetworking

  • Example 工程

项目文件目录中存在一个名为 Example 的工程,这个工程是你选择 Would you like to include a demo application with your library? 中选择 Yes 时为你添加的,这个还是很有用的,在你开发过程中可以通过它来集成测试组件功能的正确性、完整性。 我们先打开这个 Example 来看下:

项目结构

这个 Example 已经为你的组件创建了索引文件 podspec,并且集成了该组件。我们来看下 ExamplePodfile 的内容:

use_frameworks!

platform :ios, '8.0'

target 'LLNetworking_Example' do
  pod 'LLNetworking', :path => '../'

  target 'LLNetworking_Tests' do
    inherit! :search_paths

    pod 'FBSnapshotTestCase'
  end
end

其中为你集成了一个测试用例 pod 'FBSnapshotTestCase',目前可以忽略。

我们可以看到: pod 'LLNetworking', :path => '../' 这一句,path 路径指向了本地路径,对应 LLNetworking 主目录下:

组件目录

这个文件夹下,一个存放你的各种类文件,一个存放图片资源等。

  • podspec 文件

在你回答之前问题之后,pod 为你自动创建了该文件,并执行了 pod install 命令,该命令会找到组件的索引文件(也在本地) LLNetworking.podspec

#
# Be sure to run `pod lib lint LLNetworking.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             = 'LLNetworking'
  s.version          = '0.1.0'
  s.summary          = 'A short description of LLNetworking.'

# 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://github.com/LOLITA0164/LLNetworking'
  # s.screenshots     = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'LOLITA0164' => '476512340@qq.com' }
  s.source           = { :git => 'https://github.com/LOLITA0164/LLNetworking.git', :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

  s.ios.deployment_target = '8.0'

  s.source_files = 'LLNetworking/Classes/**/*'
  
  # s.resource_bundles = {
  #   'LLNetworking' => ['LLNetworking/Assets/*.png']
  # }

  # s.public_header_files = 'Pod/Classes/**/*.h'
  # s.frameworks = 'UIKit', 'MapKit'
  # s.dependency 'AFNetworking', '~> 2.3'
end

该文件为你的组件自动配置了一些基本的信息,因为我之前使用过 trunk 登陆过,所以这里有的的账号信息。当然这些信息是需要你根据情况修改的,更多的配置你可以搜索相关文档。

注意:这里的 Git 地址目前是找不到的,后期需要自己关联。

设置共享文件

podspec 文件中 s.source_files = 'LLNetworking/Classes/**/*' 指代共享的资源路径,我们需要将共享的文件放到这里来。

共享文件夹

我们打开组件的目录查看,可以看到这里已经有了名为 ReplaceMe 的文件了,这暗示你用共享文件替换它。

podspec 文件中还有一个被注释掉的:

# s.resource_bundles = {
  #   'LLNetworking' => ['LLNetworking/Assets/*.png']
  # }

这个目录中存放一些图片等资源,当你需要的时候可以开启来。

我们来创建一个 LLNetworking 类:

@interface LLNetworking : NSObject
-(NSString*)getSomething;
@end

@implementation LLNetworking
-(NSString *)getSomething{
    return @"test method.";
}
@end

将其移动到组件的共享目录下并删除掉空文件ReplaceMe

设置共享文件

这样,我们就设置好了共享的内容,即组件开发好了。接下来,我们使用 Example 工程来使用这个组件的内容。

终端进入 Example 工程目录下,执行 pod install 命令来安装组件。

安装新的组件

我们发现,Example 项目中 Pods/Development Pods/LLNetworking 下,多出来最新添加的文件。

使用组件

我们安装好组件之后来使用一下组件的功能,就像使用三方库那样:

#import <LLNetworking/LLNetworking.h>

-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    LLNetworking * networking = LLNetworking.new;
    NSLog(@"%@",networking.getSomething);
}

控制台输出:

2019-11-08 17:14:47.455341+0800 LLNetworking_Example[7038:1682304] test method.

这表示功能正常。

在组件开发过程中,使用 pod 'LLNetworking', :path => '../' 将路径指向本地是很有必要的,方便测试你的组件配置是否正确,功能是否完善,相比推到远程、发布再集成,这方便太多了。

三方依赖库

有时候,我们的组件还依赖其他的组件,又或者是三方库。我们通过 s.dependency 字段去设置,多个库可以分开写多次。

Podfiles 模版里最后一条已经为我们添加好了,所依赖的是 AFNetworking ,正好是我们网络请求组件所依赖的,我们把它开启,重新 pod install

Analyzing dependencies
Fetching podspec for `LLNetworking` from `../`
Downloading dependencies
Installing AFNetworking (2.7.0)
……

我们发现,Example 自动拉取了组件 LLNetworking 所依赖的其他组件。CocoaPods 工具的另外一个优点就是,多个组件依赖同一个组件时,它会自动帮你检测安装,而不会重复导入。

本地组件和远程组件

我们发现 Example 工程的 Pods中,本地开发的组件和远程发布的组件被分别放在了不同的目录下。

有了 AFNetworking 之后,你就可以修改你的网络请求组件了:

#import <AFNetworking/AFNetworking.h>
@interface LLNetworking : NSObject
@property(strong,nonatomic)NSURLSessionDataTask *task;
- (NSURLSessionDataTask *)POSTWithURLString:(NSString *)URLString parameters:(id)parameters success:(void (^)(id responseObject))success failure:(void (^)(id error))failure;
@end

@implementation LLNetworking
- (NSURLSessionDataTask *)POSTWithURLString:(NSString *)URLString parameters:(id)parameters success:(void (^)(id responseObject))success failure:(void (^)(id error))failure{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer.timeoutInterval = 20;
   _task =  [manager POST:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       if (success) {
           success(@{@"status":@"success"});
       }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failure) {
            failure(@{@"status":@"failure"});
        }
    }];
    return _task;
}
@end

修改好之后,还不能直接在 Example 中使用,需要卸载组件再重新安装。注释掉 pod 'LLNetworking', :path => '../' 之后执行 pod install 即可完成卸载。

至此,你完成了组件的创建、文件共享、本地化测试使用和更新。但是,我们的组件毕竟是要服务于宿主工程的,如果仅仅只能是通过本地集成,那意义不大,我们要将其关联到远程服务器,推送到本地搭建的 GitLab,又或者是 GitHub码云Coding 等平台。

关联远程仓库

在模版 podspec 文件中,已经帮我们指定了一个 GitHub 的仓库地址,

s.homepage         = 'https://github.com/LOLITA0164/LLNetworking'

你可以使用它或者进行修改它。我们这里选择使用它,先去 GitHub 创建对应的仓库。

创建演示demo

在最初创建组件时,系统已经帮我们创建好了本地 Git 仓库,进入到项目中,显示出隐藏文件夹就可以看到(command+shift+. 显隐):

本地git仓库

如果没有,你可以使用命令 git init 创建一个。现在,我们要将之前的修改进行提交(本地提交)。

git commit -am "第一次提交"  

然后我们要把本地的 Git 仓库和刚刚创建的远程仓库进行关联。如何关联呢?你在网站上创建项目后有了这样的提示:

关联远程仓库

这里有三种:创建一个新的仓库,推送一个已存在的仓库以及从其他仓库导入。我们这里使用第二种即可。

添加远程仓库:

git remote add origin https://github.com/LOLITA0164/LLNetworking.git

将本地内容推送到远程仓库:

git push -u origin master

可能会出现让你登陆验证,输入你的用户名和密码即可。出现以下信息即表示推送成功。

remote: Resolving deltas: 100% (49/49), done.
To https://github.com/LOLITA0164/LLNetworking.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

回到 GitHub 刷新一下即可看到你的提交记录。

上述是通过终端命令进行 git 操作,如果你并不熟悉 git 命令,你大可以使用便捷的可视化工具(上一章节有所提及),仅需简单的点击操作即可完成项目的管理。

tag 并发布到 Cocoapods

打标签

至此,我们已经成功的将本地仓库关联并推送到远程仓库,现在我们要发布一个可用的组件。

首先我们要给当前项目打一个 tag 版本号,在 podspec 中:

s.version          = '0.1.0'

指定的版本号是 0.1.0,那么我们就同样打个 0.1.0tag:

$ git tag 0.1.0  // 打 tag
$ git push --tags  // 推送到远程

tag 默认在当前分支上,因为这里只有 master,所以不用切换分支,如果后期有其他分支,注意别弄错了。

刷新页面,项目的 release 选项中会出现刚刚打的版本。

打tag

你也可以直接在页面的 release 下添加新的 tag,点击 release 可以看到编辑页面:

在线打包

发布到 CocoaPods

由于我们创建的项目以及标签的版本号都是沿用了 podspec 文件中的信息,因此可以直接验证 podspec 文件信息是否可以通过验证,如果需要调整,调整之后最好同样先验证:

pod spec lint

podspec 文件的版本号一定要和 tag 保持一致。

如果通过验证,那么你会看到类似下面的提示,绿色的 passed validation

验证通过

现在可以将 podspec 文件提交到 CocoaPods 上了:

首先要通过 trunk 注册生成一条会话:

// pod trunk register 邮箱 用户名 描述
pod trunk register 476512340@qq.com LOLITA0164 --description=组件化demo 

然后去邮箱进行验证,验证成功会出现下面页面:

验证通过

现在,就可以将 podspec 提交给 CocoaPods 了。这个文件将是别人搜索你的组件的索引。

pod trunk push LLNetworking.podspec --allow-warnings

上传完成之后,接可以通过 pod search LLNetworking 搜索到自己的组件了,如果搜索不到,删除本地的搜索文件,命令 :

rm ~/Library/Caches/CocoaPods/search_index.json

重新 search 产生新的搜索文件。

发布新版本则需要打新的 tag,重新编辑 podspec 文件,然后再次提交给 CocoaPods

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值