使用cocoapods进行联编

cocoapods是管理Objective-C 项目中各种库依赖的工具。系统的使用方法,可参考其官方网站,本文详细介绍一下使用cocoapods进行联编的方法。在给出具体可行的步骤之前,会有一些原理性的介绍。如果读者只为求实施方法,可点击这里。

podfile 与 podspec文件

在使用cocoapods过程中,会产生两个重要的文件——podfile与podspec。podfile在引用项目中使用,说明当前项目使用什么framework,这些framework去哪里寻找。podfile的文件格式比较简单(与podspec皆为ruby格式的代码),示例片段如下:

platform :ios, '6.0'
target "demo_app_main" do
	pod 'demo_framework', :path => '~/WorkSpace/demo_ios/demo_framework'
	pod 'demo_framework_root', :path => '~/WorkSpace/demo_ios/demo_framework_root'
	pod 'pop',  '~> 1.0' 
        #pod ‘framework1’, ‘version’ 或者 pod ‘framework1’, :head
        #pod ‘framework2’, :git => ‘xxxx.git’ :branch => ‘branch'
        #pod ‘framework3’, :path => ‘workspace的路径’
end

关键语句为:pod <framework名> <描述framework的podspec文件的地址>

命令行切换到项目目录之后,运行 pod install,实际是告诉cocoapods去读取podfile,寻找podspec文件,将podspec文件描述的framework添加进来。<描述framework的podspec文件的地址> 可以有多种格式,也可以使用远程或者本地的git地址与分支。如果没有指明podspec的地址,那么则从cocoapods默认的源(默认路径为~/.cocoapods/repo)中寻找。那么,podspec文件中是什么呢?下面是一份podspec文件范例:

Pod::Spec.new do |s|
  s.name         = "demo_framework"
  s.version      = "0.0.1"
  s.summary      = "A short description of demo_framework."
  s.homepage     = "http://EXAMPLE/demo_framework"
  s.license      = "MIT (example)"
  #s.source       = { :git => "http://EXAMPLE/demo_framework.git", :tag => "0.0.1" }
  s.source_files  = "demo_framework/*.{h,m}"
  s.exclude_files = "demo_framework/Exclude"
  s.public_header_files = "demo_framework/*.h"
  # s.resource  = "icon.png"
  # s.resources = "Resources/*.png"
  # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
  # s.framework  = "SomeFramework"
  # s.frameworks = "SomeFramework", "AnotherFramework"
  # s.requires_arc = true
  # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
  # s.dependency 'demo_framework_root', '0.0.1' 
end

‘#’表示注释。在此份podspec文件中,重要的是 s.name,s.version,s.dependency,s.source_files几个段。分别描述了当前framework的名称,版本,引用内容(对联编特别重要),所依赖的其他的framework。cocoapods官网上详细地介绍了podspec文件其他的属性字段,可以在命令行中通过如下语句创建podspec文件。

pod spec create <podspec的文件名>

注:spec,specification,规格之意。

 一次依赖的联编

在没有使用cocoapods管理framework的时候,可以直接将framework的工程文件拖到引用工程中去,然后在引用工程中设置framework包含,如图:

drag_framework_to_project

这时候,会有提示出现:

drag_framework_to_project_choose

选择Yes,然后在项目的Build Phase中,引入framework的头文件即可。

drag_framework_to_project_build_phase

引入头文件之后,就可以进行联编了。对于cocoapods管理的引用工程,也可以用此方法。但是当framework也被cocoapods管理的时候,就无法使用这种方法了。因为,运行pod install之后,framework工程项目会被后缀为.xcworkspace的文件取代,而将此工程文件拖入引用工程之后,xcode无法识别。正确的做法是 ,在被引用framework工程中创建一个描述framework的podspec(参见前文的代码范例,如果是运行 pod spec create 命令创建的,需要注释掉s.source一行;然后修改s.source_files,这个文件会声明引用工程引入被引用工程中相应文件的快捷方式),然后在引用工程中创建一个podfile(参见前文的代码范例,路径使用:path。),之后运行pod install。之后,打开.xcworkspace项目文件,会发现会多出pod->Development Pods目录,里面是被引用工程源文件的快捷方式,于是联编很方便。

注: 本文所讲的framework是使用iOS-Universal-Framework创建的,具体使用请百科之。

多次依赖的联编

假设A是主工程。A依赖B,B依赖C。如果A中的podfile引用了B(中的podspec),B中的podfile引用了C(中的podspec)。A中运行pod install,B中运行pod install。如你所料,这样是行不通的。

大略会提示C中的某些文件找不到,自然,因为A的podfile在引用B的时候,并不知道C的存在。注意B的podspec是和B的podfile没有关系的。我们需要修改B的podspce中的s.dependency字段,将B工程引用的C加进来。如果C工程是一个编译好了的framework的话,添加pod源,使用类似【 s.dependency ‘demo_framework_root’, ‘0.0.1’ 】语句是可以的,不过B引用的C是源代码,并且我们希望在编辑源码A的时候可以修改C,这样就需要修改s.dependency字段。也许你想到了使用:git或者:path,就像podfile中的pod字段一样,很遗憾,cocoapods不支持在podspec中使用:path或:git。在编辑工程A的时候,依然会提示C中的某些文件没有找到。这也许算是cocoapods中的一个不足点,读者可以参考这篇帖子。然而联编不可不进行,可以采用如下方法。

在A的podfile中,同时添加工程B与工程C的podspec地址,不需要编写B的podspec的s.dependency字段。然后执行A的pod install,可以发现在工程A中,B与C的源码都被引入进来了。这时候联编,如果修改了cocoapods管理的被引用文件,是可以反映到B与C中的。这样子,C工程可以单独编辑编译,B工程可以使用cocoapods编辑编译,A工程可以使用cocoapods编辑编译,开发工作完美解决。demo中demo_app_main是引用工程,demo_framework是被引用工程,demo_framerwork_root是二级被引用工程,按照上述思路进行联编之后,demo_app_main的工程展示如下:

demo_app_main_project_shotscreen

podfile与podspec文件的地址在这里.

之后怎么办 …

Git下的多人开发

在必须要联编的情况下,可以将引用工程与被引用工程pull下来,针对被引用工程配置一个podfile,其s.source字段置空。另外配置一份podfile放在引用工程中,将其引用路径指向本地被引工程的开发目录,此podfile不需提交到版本库。每次开发的时候,pull一下,然后重新pod install一下(甚至不需要,如果其他第三方framework没有更新的话),然后开发就可以了。开发之后push一下。其他人的配置与之相同。这样放在本地的podfile与提交到版本库中的podspec文件是不需要经常修改的,开发配置十分简单。

发布独立的framework/源码供第三方使用

如果研究~/.cocoapods/repo路径中的内容你会发现,其实cocoapods提供了一个开源framework的列表,在~/.cocoapods/repo/master目录下,其目录结构为:

–master
—-Specs
——many dirs  #很多库名命名的文件夹
——–version dirs  #以库版本库命名的文件夹
———-.podspec.json file.  #这个文件和 .podspec 文件的作用应该是一样的。

这个spec repo 是开源的,地址在这里,并且在不断整理中,这样其他人在引用第三方的开源库的时候就比较方便了。但是有时候项目也需要引用一些闭源的库,故需要添加其他的源。添加其他的源,可以创建一个版本库。其目录结构为:

–pod repo source name  #自己创建的源的名称
—-many dir  #很多库名命名的文件夹
——version dir  #以库版本库命名的文件夹
——–.podspec file

将我们创建的spec 库放到git中,然后运行 pod repos add [git地址]就可以将我们自己创建的spec库添加进来了。这部分也可参考官方文档。回到本节来,我们开发好了framework之后,可以提供给其他人一个framework,也可以以github地址的方式给其他人源码,然后在这个工程中创建一个podspec文件来说明。别人在使用的,别人只需要在podfile中加入这个git地址就可以;如果你创建的是开源项目,你也可以将你创建的podspec提交到 cocoapods 的开源spec中。在运行pod install的时候,cocoapods会自动将这些被引用工程拉到本地编译。

当然很多情况下,framework开发者只想给外部提供一个二进制进口,这样也是可以的。只是在podfile的路径中,需要指明这个二进制framewok的git地址或者本地地址。

其他的

感觉cocoapod是一个很好的项目,使用的好的话,可以很优雅地管理十分复杂的依赖。本文主要写的是联编技巧。官网文档写的不多,也不复杂,初用者最好话点时间读读,以晓工具全貌。

Tagged with: , , , , ,

发表评论

邮箱地址不会被公开。 必填项已用*标注

*