【iOS】使用CocoaPods向包含多个Project的Workspace中的Framework项目安装第三方库(Google Maps SDK)

0. 关于CocoaPods

参照 CocoaPods Getting Started guide, 安装如下。使用macOS默认自带的Ruby即可安装,不需要任何前置安装。

1
$ sudo gem install cocoapods

1. 使用CocoaPods向单个项目中安装第三方库(Google Maps SDK)

参照 Get Started | Maps SDK for iOS | Google Developers,步骤如下:

  1. 如果还没有Xcode项目(project)则新建一个。
  2. 在项目根目录下新建文件Podfile,用于定义项目中库的依赖关系。
  3. 编辑文件Podfile,加入如下内容并保存:
    1
    2
    3
    4
    5
    source 'https://github.com/CocoaPods/Specs.git'
    target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
    pod 'GoogleMaps'
    pod 'GooglePlaces'
    end

其中,YOUR_APPLICATION_TARGET_NAME_HERE需要改为Xcode项目中Target的名称。该配置将向Target中加入GoogleMapsGooglePlaces两个库。

  1. 打开terminal,进入项目根目录并运行pod install

    1
    2
    $ cd /path/to/project
    $ pod install
  2. 如无异常信息输出,则安装成功。此时CocoaPods会在项目根目录自动新建工作空间(Workspace)配置文件.xcworkspace。如目录下已存在.xcworkspace文件,则CocoaPods会自动修改它。

  3. 关闭Xcode,双击.xcworkspace(而不是.xcodeproj)打开项目。
  4. 使用新添加的库。

2. 使用CocoaPods向包含多个项目的Workspace中安装第三方库

首先,该Workspace中的目录结构大致示意如下

  • [Workspace root]
    • workspace.xcworkspace
    • [Project1 folder]
      • project1.xcodeproj
      • [AppTarget folder]
    • [Project2 folder]
      • project2.xcodeproj
      • [FrameworkTarget folder]

其中,Project2Project1的依赖,其生成的Framework被Project1的Target所引用。此时我们的需求是向Project2中使用CocoaPods加入第三方库(Google Maps SDK).

尝试一:在Project2中独立安装第三方库(不成功)

即在[Project2 folder]下新建Podfile文件并运行pod install

1
2
3
4
5
source 'https://github.com/CocoaPods/Specs.git'
target 'FrameworkTarget' do
pod 'GoogleMaps'
pod 'GooglePlaces'
end

结果:

  1. 在编写代码时能正常显示新加入的库中的内容
  2. 在workspace中编译TargetApp不通过,提示找不到新加库的头文件
  3. 在workspace中单独编译TargetFramework不通过,提示找不到新加库的头文件
  4. 打开Project2中由CocoaPods自动生成的.xcworkspace文件,单独编译Framework成功。

尝试二:在Workspace中建立Podfile统一安装管理多个项目的第三方库

卸载项目中已安装的CocoaPods库

使用CocoaPods-deintegrate(最好事先备份项目):

1
2
3
$ [sudo] gem install cocoapods-deintegrate
$ cd folder/to/the/project
$ pod deintegrate

如无错误信息输出,卸载成功后,项目目录下残留PodfilePodfile.lock.xcworkspace三个文件,需手动删除。

在Workspace根目录下新建Podfile文件并执行安装

参照:
iOS 如何在一个存在多个project的workspace中引入cocoapods管理第三方类库
iOS 如何在一个已经存在多个project的workspace中引入cocoapods管理第三方类库

新建Podfile如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
platform :ios, '8.0'

workspace 'Workspace'

project 'Project1 folder/project1.xcodeproj'
project 'Project2 folder/project2.xcodeproj'

source 'https://github.com/CocoaPods/Specs.git'
target 'FrameworkTarget' do
project 'Project2 folder/project2.xcodeproj'
pod 'GoogleMaps'
pod 'GooglePlaces'
end

执行pod install安装后,workspace.xcworkspace将被修改。重新打开后可使用新加入的库编写代码。

结果:

  1. 在编写代码时能正常显示新加入的库中的内容
  2. 在workspace中编译TargetApp不通过,提示找不到新加库的头文件
  3. 在workspace中单独编译TargetFramework通过

查找问题并修正

分别查看FrameworkTarget和AppTarget的Build Settings中的Framework Search Paths等设置,发现FrameworkTarget中正确设定了CocoaPods相关的路径值,而在AppTarget中均为空值。将Podfile修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
platform :ios, '8.0'

workspace 'Workspace'

project 'Project1 folder/project1.xcodeproj'
project 'Project2 folder/project2.xcodeproj'

source 'https://github.com/CocoaPods/Specs.git'
target 'FrameworkTarget' do
project 'Project2 folder/project2.xcodeproj'
pod 'GoogleMaps'
pod 'GooglePlaces'
end

target 'AppTarget' do
project 'Project1 folder/project1.xcodeproj'
pod 'GoogleMaps'
pod 'GooglePlaces'
end

结果: 编译、执行通过。

3. 小结

使用CocoaPods在多项目的Workspace中安装管理第三方库时,必须注意项目间的依赖关系和搜索路径的相关配置是否正确。

本文应该并未实现最终解决,因为目前的配置似乎违背了Project2作为Framework可以独立存在的初衷。但Project2独立编译生成的Framework应该仍然可以在其他项目中正常使用(尚未验证)。文中在Project1中直接引用Project2的目的是方便调试。