zoukankan      html  css  js  c++  java
  • [转]iOS系列译文:深入理解 CocoaPods

    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 参数。现在,运行

    1
    pod install --verbose

    将会出现以下执行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    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的魔力如何显现。

    原文链接: Michele Titolo   翻译: 伯乐在线 programmer.du
    译文链接: http://blog.jobbole.com/53365/

  • 相关阅读:
    some requirement checks failed
    FTP下载文件时拒绝登陆申请怎么办?
    Linux查看与设定别名
    如何编写shell脚本
    Linux shell是什么
    Linux命令大全之查看登陆用户信息
    Linux命令大全之挂载命令
    论第二次作业之输入输出格式怎么合格(才疏学浅说的不对轻点喷我)
    文件词数统计
    软件工程作业--第一周
  • 原文地址:https://www.cnblogs.com/crazypebble/p/3580704.html
Copyright © 2011-2022 走看看