使用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包含,如图:
这时候,会有提示出现:
选择Yes,然后在项目的Build Phase中,引入framework的头文件即可。
引入头文件之后,就可以进行联编了。对于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的工程展示如下:
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是一个很好的项目,使用的好的话,可以很优雅地管理十分复杂的依赖。本文主要写的是联编技巧。官网文档写的不多,也不复杂,初用者最好话点时间读读,以晓工具全貌。
发表评论