zoukankan      html  css  js  c++  java
  • CocoaPods——深入理解 CocoaPods

    本文由 伯乐在线 - programmer.du 翻译自 Michele Titolo。欢迎加入技术翻译小组。转载请参见文章末尾处的要求。

      Cocoapods是 OS X 和 iOS 下的一个第三方库管理工具。你能使用CocoaPods添加被称作“Pods”的依赖库,并轻松管理它们的版本,而不用考虑当前的时间和开发环境。

      Cocoapods意义体现在两个方面。首先,引入第三方库无可避免地要进行各种各样的配置。对于Objective-C的初级开发者来说,项目配置可是一件艰巨的任务。在配置编译阶段和链接器选项的过程中,极有可能引入许多人为的错误。而CocoaPods简化了这一切,它能自动配置编译选项,拯救了开发者。

      其次,使用CocoaPods可以很方便地查找新的第三方库。当然,这可不是说让你七拼八凑别人代码而开发出一个“移栽”应用。而是让你找到真正好用的库,缩短你的开发周期,提升你的代码质量。

      接下来,我们将通过分析pod安装的过程,一步步揭示CocoaPods背后的技术。

    核心组件

      CocoaPods是用ruby写的,并划分成了若干个Gem包。CocoaPods在解析执行过程中最重要的几个包的路径分别是:CocoaPods/CocoaPods、 CocoaPods/Core 和 CocoaPods/Xcodeproj。

      CocoaPods / CocoaPod

      这是面向用户的组件,每当你执行一个pod命令时,这个组件将被激活。它包括了所有实用CocoaPods的功能,并且还能调用其他gem包来执行任务。

       CocoaPods / Core

      Core gem提供了与CocoaPods相关的文件(主要是Podfile和podspecs)的处理。

      Podfile

      Podfile用于配置项目所需要的第三方库。它能被高度定制,所以你可以尽可能地给它添加你想要的特性。如果您还想对Podfile了解更多的话,请查看Podfile指南(地址 http://guides.cocoapods.org/syntax/podfile.html)。

      Podspec

      .podspec文件描述了一个库将怎样被添加进工程中。.podspec文件可以标识该第三方库所需要的源码文件、依赖库、编译选项,以及其他第三方库需要的配置。

      CocoaPods / Xcodeproj

      这个包负责工程文件直接关系的处理。它能创建以及修改.xcodeproj文件和.xcworkspace文件。它也可以作为一个独立的包使用,当你要编写修改项目文件的脚本时,可以考虑使用CocoaPods/Xcodeproj。

    运行 pod install 命令

      pod install的执行引发了很多操作。了解底层运行过程最简单的方式就是给pod install语句添加 –verbose 参数。现在,运行

    pod install --verbose

      将会出现以下执行结果:

    Analyzing dependencies 
    
    Updating spec repositories
    Updating spec repo `master` 
    $ /usr/bin/git pull
    Already up-to-date.
    
    Finding Podfile changes
    - AFNetworking
    - HockeySDK
    
    Resolving dependencies of `Podfile`
    Resolving dependencies for target `Pods' (iOS 6.0)
    - AFNetworking (= 1.2.1)
    - SDWebImage (= 3.2)
    - SDWebImage/Core
    
    Comparing resolved specification to the sandbox manifest
    - AFNetworking
    - HockeySDK
    
    Downloading dependencies
    
    -> Using AFNetworking (1.2.1)
    
    -> Using HockeySDK (3.0.0)
    - Running pre install hooks
    - HockeySDK
    
    Generating Pods project
    - Creating Pods project
    - Adding source files to Pods project
    - Adding frameworks to Pods project
    - Adding libraries to Pods project
    - Adding resources to Pods project
    - Linking headers
    - Installing libraries
    - Installing target `Pods-AFNetworking` iOS 6.0
    - Adding Build files
    - Adding resource bundles to Pods project
    - Generating public xcconfig file at `Pods/Pods-AFNetworking.xcconfig`
    - Generating private xcconfig file at `Pods/Pods-AFNetworking-Private.xcconfig`
    - Generating prefix header at `Pods/Pods-AFNetworking-prefix.pch`
    - Generating dummy source file at `Pods/Pods-AFNetworking-dummy.m`
    - Installing target `Pods-HockeySDK` iOS 6.0
    - Adding Build files
    - Adding resource bundles to Pods project
    - Generating public xcconfig file at `Pods/Pods-HockeySDK.xcconfig`
    - Generating private xcconfig file at `Pods/Pods-HockeySDK-Private.xcconfig`
    
     - Generating prefix header at `Pods/Pods-HockeySDK-prefix.pch`
    
    - Generating dummy source file at `Pods/Pods-HockeySDK-dummy.m`
    - Installing target `Pods` iOS 6.0
    - Generating xcconfig file at `Pods/Pods.xcconfig`
    - Generating target environment header at `Pods/Pods-environment.h`
    - Generating copy resources script at `Pods/Pods-resources.sh`
    - Generating acknowledgements at `Pods/Pods-acknowledgements.plist`
    - Generating acknowledgements at `Pods/Pods-acknowledgements.markdown`
    - Generating dummy source file at `Pods/Pods-dummy.m`
    - Running post install hooks
    - Writing Xcode project file to `Pods/Pods.xcodeproj`
    - Writing Lockfile in `Podfile.lock`
    - Writing Manifest in `Pods/Manifest.lock`
    Integrating client project

      整个过程中执行了很多操作,不过把它们分解之后,会发现它们都很简单。让我们逐步来分析。

      阅读Podfile文件

      你是否吐槽过Podfile的语法太过诡异,其实这是ruby的语法而不是OC。相较而言,Podfile要比现有的其他格式更加简单好用一些。

      安装的第一步是要弄清楚哪些第三方库被显式或隐式地声明了。CocoaPods加载podspecs文件时,获取了第三方库的名称及版本列表。Podsspecs文件存储在本地,路径为~/.cocoapods。

      版本控制和冲突

      CocoaPods使用语义版本命名约定来解决对版本的依赖。由于冲突解决系统建立在非重大更改的补丁版本之间,这使得解决依赖关系要容易得多。举个栗子,两个完全不同的第三方库同时依赖CocoaLumberjack。它们其中一个依赖的版本是2.3.1,而另一个则为2.3.3,解析器可以自动使用较新的版本,在这里则是2.3.3,因为这可以与2.3.1向后兼容。

      但这并不总是有效。有许多第三方库还并不支持这个约定,这让解决方案变得非常复杂。

      当然,总是会有一些冲突需要手工解决。如果一个第三方库依赖CocoaLumberjack 1.2.5,而另一个依赖CocoaLumberjack 2.3.1,最后只能靠调用这两个第三方库的用户来手动地决定CocoaLumberjack的版本了。

      加载源码

      CocoaPods执行的下一个步骤是加载源代码。每个.podspec文件都包含了源代码的索引,这些索引一般指向了一个git地址或者git tag。它们以commit SHA码的方式存储在 ~/Library/Caches/CocoaPods中。而在这些路径中创建文件则由 Core 包负责。

      源代码将依照Podfile、.podspec和缓存文件的信息下载到相应的第三方库路径。

      生成Pods.xcodeproj

      每次pod install 执行后并且检测到改动时,Pods.xcodeproj文件将呗Xcodeproj gem更新。如果Pods.xcodeproj文件不存在,则会以默认配置生成,若已存在,则Pods.xcodeproj会使用现有的配置。

      安装第三方库

      当Cocoapods向项目中增加了一个第三方库的时候,不仅仅是将添加代码这么简单。由于每个第三方库有不同的target,所以每次添加第三方库时,都只有几个文件被添加。每个源代码都需要:

    • 一个包含编译选项的.xcconfig文件
    • 一个同时拥有编译设置和CocoaPods默认配置的私有.xcconfig文件
    • 编译所必须的prefix.pch文件
    • 另一个编译必须的文件dummy.m

      一旦每个pod的target都完成了以上步骤,整个Pods的Target就会被创建。这增加了相同的文件,与另外几个。如果有源代码中包含了资源bundle,向app的target中添加bundle的方式将写入Pods-Resources.sh。还有一个叫Pods-environment.h的文件,文件中含有许多检查组件是否来自pod的宏定义。最后,将生成两个确认文件,一个.plist文件,一个用于给用户查阅许可信息的markdown文件。

      写入到磁盘

      直到现在,许多已完成的过程都使用的是内存中的对象。为了让这些过程的结果可重复被使用,我们需要将所有结果都记录在一个文件中。所以Pods.xcodeproj和另外两个非常重要的文件:Podfile.lock和Manifest.lock都将被写入磁盘。

      Podfile.lock

      这是CocoaPods创建的最重要的文件之一。它记录了需要被安装的pod的每个已安装的版本。如果你想知道已安装的pod是哪个版本,可以查看这个文件。推荐将Podfile.lock文件加入到版本控制中,这有助于整个团队的一致性。

      Manifest.lock

      这是每次运行pod install时创建的Podfile.lock文件的副本。如果你见过“沙盒文件和Podfile.lock文件不同步”的错误,这个错误就是因Manifest.lock文件和Podfile.lock文件不一样引起。由于Pods所在的目录并不总在版本控制之下,这样可以保证开发者运行app之前都能更新他们的pods,否则app可能会crash,或者在一些不太明显的地方编译失败

      xcproj

      如果您已经依照我们的建议在系统上安装了xcproj,它会将您的Pods.xcodeproj文件转换成就旧有ASCII格式的plist文件。为什么要这么做呢?因为Xcode所依赖和使用的plist在很久以前就已经不被其他软件支持了。如果没有xcproj,你的Pods.xcodeproj文件将会以XML格式的plist文件存储,当你用Xcode打开它时,它会被改写,造成大量的文件冲突。

    运行结果

      运行pod install的最终结果是许多文件被添加到你的工程和系统中。这个过程通常只需要几秒钟。当然没有Cocoapods这些事也都可以完成。只不过所花的时间就不仅仅是几秒而已了。

    旁注:持续集成

      CocoaPods和持续集成在一起非常融洽。虽然持续集成很大程度上取决于你的项目配置,但Cocoapods依然能很容易地对项目进行编译。

      Pods文件夹已加入版本控制的持续集成

      如果包括Pods文件夹的一切东西都在版本控制之中,那么你不需要特别做什么就能够持续集成。由于编译时必须指定一个scheme,所以只需要保证使用了正确的scheme即可。

      没有Pods文件夹的持续集成

      如果你的Pods文件夹没有被纳入版本控制之中,那么你需要一些额外的步骤来保证持续集成的顺利进行。最起码,Podfile文件要放入版本控制之中。另外强烈建议将生成的.xcworkspace文件和Podfile.lock文件纳入版本控制,这样不仅简单方便,更能保证所使用的Pod是正确的版本。

      一旦配置完毕,让CocoaPods在CI上正确运行的关键是保证每次编译之前都执行了pod install。在大多数系统中,譬如Jenkins或者Travis,你只用把“pod install”定义为一个编译步骤即可(实际上,Travis会自动执行pod install)。随着Xcode Bot的发布,我们还没有找到能像书写的这么流畅的解决方案,不过我们正朝着解决方案努力,一旦成功,我们将会立即分享。

    结束语

      CocoaPods简化了OC的开发流程,我们的目标是让第三方库更容易被发现和添加。了解CocoaPods的原理能让你做出更好的App。我们沿着CocoaPods的整个流程一步步执行,从载入specs文件和源代码、创建.xcodeproj文件和所有组件到将所有文件写入磁盘。所以接下来,我们运行 pod install –verbose,静静观察CocoaPods的魔力如何显现。

  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/sunnyke/p/4490577.html
Copyright © 2011-2022 走看看