使用CocoaPods管理第三方库

iOS 中可以使用 Workspace 来管理多项目,而 CocoaPods 是依赖管理工具,用来管理第三方类库,用起来相当方便。初步的想法是将自己的所有项目移动到 Workspace 中,并通过 CocoaPods 共同管理第三方类库的同时,将 Workspace 下的所有项目需要的一些自定义的组建和框架,加入到 Workspace 下的一个自定义的 Library 或 Framework,作为依赖分别编译到各个项目中。当然这里自定义的 Library 或 Framework 也可以直接自定义一个 CocoaPods 的开发库,来封装公共代码。

关于 CocoaPods 的使用网上已经有太多的教程了,我之所以再写一遍就是想自己跟着步骤操作,记录一下自己所遇到的问题以及解决方案,以便日后方便查阅。你也可以这样说 CocoaPods 只是一个第三方的工具,不用它我们也完全可以自己实现这些管理。 我们来看看在没有用之前,我们一般要手动导入第三方的 Library 或 Framework,有的可能还要导入头文件,某些文件还需要设置 -fno-objc-arc,在 Link Binary With Libraries 里还要导入这个第三方类库所要依赖的系统库,完了还要设置 Header Search Paths,Library Search Paths,Framework Search Paths 等等一系列操作,完了一顿操作之后一编译,发现报各种错误信息。各种第三方类库也一直在不断更新,每当需要更新时都得重复一遍上面这些操作,特别不方便管理。CocoaPods 的出现的确帮了开发者一个大忙,所以,好的工具为什么不拿来用呢。

安装

安装 CocoaPods 需要 Ruby 环境,因为 Mac 自带 Ruby 又为我们节省了不少操作。这里需要过墙:

1
2
3
$ gem sources --remove https://rubygems.org/
$ gem sources -a https://gems.ruby-china.org/
$ gem sources -l

如果打印出以下信息则说明成功了:

1
2
*** CURRENT SOURCES ***
https://gems.ruby-china.org/

另外,如果之前使用的是淘宝的镜像( https://ruby.taobao.org/ ),但现在已经不可用了。可以查看当前镜像,先移除老版本的镜像,再新增可用的镜像,检查使用替换镜像位置成功,确保只有 gems.ruby-china.com。

1
2
3
$ gem sources -r https://rubygems.org/
$ gem sources -a https://gems.ruby-china.com/
$ gem sources -l

之后执行

1
$ pod setup

如果此处出现 -bash: pod: command not found 的错误信息,则需要执行:

1
sudo gem install -n /usr/local/bin cocoapods

此处注意: 进入 Setting up CocoaPods master repo 开始下载镜像,此时可以用新开一个终端窗口,输入 cd ~/.cocoapods/ 命令行跳到cocoapods文件夹内,执行 du -sh * 查看已经在下载的文件夹的大小。

然后在这里可以升级一下 gem :

1
$ sudo gem update —system

然后在项目的根目录下新建一个 Podfile 文件,大致实现的空能是新建一个 xxx.xcworkspace 文件作为 xxx 这个项目的入口,并为 xxx 这个项目添加两个依赖的第三方类库,分别是 Reachability、AFNetworking。

1
2
3
4
5
6
7
8
9
10
11
12
workspace 'xxx.xcworkspace'
project 'xxx/xxx.xcodeproj'

target 'xxx' do

platform :ios,'7.0'
project 'xxx/xxx.xcodeproj'

pod 'Reachability',"3.2"
pod 'AFNetworking',"~> 3.1.0"

end

终端里 cd 到 Podfile 所在文件夹,第一次的话先执行:

1
$ pod setup

完成之后继续执行:

1
$ pod install

这里可能要稍微等待一下,打印出以下信息则说明成功了。

1
2
3
4
5
6
7
8
9
Analyzing dependencies
Downloading dependencies
Installing Reachability (3.2)
Installing AFNetworking (3.1.0)
Generating Pods project
Integrating client project
[!] Please close any current Xcode sessions and use `xxx.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There are 2 dependencies from the Podfile and 2 total pods installed.

上面有一句提示需要注意一下: [!] Please close any current Xcode sessions and use xxx.xcworkspace for this project from now on. 这个项目以后都要通过项目根目录下的xxx.xcworkspace 这个文件进入项目,嗯就是这样。以后要添加或者删除第三方类库的话在 Podfile 文件里改动。之后在终端里执行以下命令即可:

1
$ pod update

如果不知道第三方类库的具体名字或版本号,可直接在终端执行:

1
$ pod search xxx

就可以搜索到相应的第三方类库和版本号了,比如: 执行 pod search json,就会出现一系列 json 相关的第三方类库。然后自己看着选吧。

另外,执行 pod installpod update 时,会先更新一次 podspec 索引( Updating local specs repositories ),相应的执行一下命令行就可以跳过这一步了:

1
2
$ pod install --no-repo-update
$ pod update --no-repo-update

完成之后你什么都不用做,直接通过项目根目录下的 xxx.xcworkspace 这个文件进入项目,编译、运行,都没有问题。

升级

执行:

1
$ sudo gem install cocoapods

报如下错误:
ERROR: While executing gem … (Gem::FilePermissionError)
You don’t have write permissions for the /usr/bin directory.
解决:

1
$ sudo gem install cocoapods -n /usr/local/bin

CocoaPods遇到的问题及解决方案

系统升级到 macOS High Sierra 后报错

系统升级到 macOS High Sierra 后,无法使用 CocoaPods,提示错误: -bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file or directory,只需执行:

1
2
3
$ sudo gem update --system
$ sudo gem install -n /usr/local/bin cocoapods
$ pod repo update

就好了。

pod search xxx 报错

报错信息:

1
2
3
4
5
6
7
8
Looking for related issues on cocoapods/cocoapods...
- pod install-- JSON::ParserError - A JSON text must at least contain two octets!
https://github.com/CocoaPods/CocoaPods/issues/6692 [closed] [7 comments]
6 weeks ago

- pod search not work JSON ParserError
https://github.com/CocoaPods/CocoaPods/issues/5172 [closed] [8 comments]
03 May 2017

解决办法:

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

再 pod search xxx。

错误信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
JSON::ParserError - A JSON text must at least contain two octets!
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/json/common.rb:156:in `initialize'
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/json/common.rb:156:in `new'
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/json/common.rb:156:in `parse'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-core-1.3.1/lib/cocoapods-core/source/manager.rb:251:in `stored_search_index'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-core-1.3.1/lib/cocoapods-core/source/manager.rb:187:in `updated_search_index'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-core-1.3.1/lib/cocoapods-core/source/manager.rb:118:in `search_by_name'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-search-1.0.0/lib/cocoapods-search/command/search.rb:87:in `local_search'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-search-1.0.0/lib/cocoapods-search/command/search.rb:63:in `run'
/Library/Ruby/Gems/2.3.0/gems/claide-1.0.2/lib/claide/command.rb:334:in `run'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-1.3.1/lib/cocoapods/command.rb:52:in `run'
/Library/Ruby/Gems/2.3.0/gems/cocoapods-1.3.1/bin/pod:55:in `<top (required)>'
/usr/local/bin/pod:23:in `load'
/usr/local/bin/pod:23:in `<main>'

解决办法:

1
2
$ sudo rm -rf ~/.cocoapods/repos/master
$ pod setup

项目集成 ReactiveCocoa 2.5,运行 UnitTest 报错(模拟器运行正常,真机报错)

报错信息如下:

1
2
*** Assertion failure in -[RACStream(Operations) flattenMap:]_block_invoke_2(), /Users/xxx/Documents/ProjectName/Pods/ReactiveCocoa/ReactiveCocoa/RACStream.m:75
2018-03-22 15:24:55.016581+0800 PhotographerTest[4475:2475101] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Value returned from -flattenMap: is not a stream: <RACDynamicSignal: 0x1c0238d60> name: '

解决办法,UnitTest 的 Target 下,加上 inherit! :search_paths(明确指定继承于父层的所有pod,默认就是继承的), 具体如下:

1
2
3
target 'ProjectNameUnitTest' do
inherit! :search_paths
end

引用图片资源未放入Bundle的Pod时,AppIcon设置无效的问题

解决方案来源

使用了 CocoaPods 的 Xcode 工程,在 iOS11 版的手机上AppIcon不显示,原因是 CocoaPods 的资源编译脚本在 iOS11 下出了点问题,需要修改脚本。两种修改方式:

方案一: 在 Podfile 添加脚本修改。

在 Podfile 添加如下代码。

1
2
3
4
5
6
7
8
post_install do |installer|
copy_pods_resources_path = "Pods/Target Support Files/Pods-[工程名]/Pods-[工程名]-resources.sh"
string_to_replace = '--compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"'
assets_compile_with_app_icon_arguments = '--compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${BUILD_DIR}/assetcatalog_generated_info.plist"'
text = File.read(copy_pods_resources_path)
new_contents = text.gsub(string_to_replace, assets_compile_with_app_icon_arguments)
File.open(copy_pods_resources_path, "w") {|file| file.puts new_contents }
end

将[工程名] 换成自己工程的名称,然后运行

1
$pod install

方案二: 手动修改

打开工程目录下: [工程名]/Pods/Target Support Files/Pods-[工程名]/Pods-[工程名]-resources.sh这个文件,替换最后一段代码:

修改前:

1
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"

修改后:

1
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${BUILD_DIR}/assetcatalog_generated_info.plist"

然后重新运行工程即可。

在这里我推荐使用方案一,方案二在执行 pod update 等操作后会再次失效,需要再次手动去修改,不够彻底。

CocoaPods 缓存地址:

1
~/Library/Caches/CocoaPods/Pods/Release

坚持原创技术分享,您的支持将鼓励我继续创作!
----------- 本文结束, 感谢您的阅读 -----------