开启 Cocoapods 新选项,加快项目索引速度

前几天 Cocoapods 1.7.0 正式版发布了,我最期待的一个功能是 Multiple Pod Projects,昨天顺手就给接入了,项目解析和索引效率有了很是明显的提高,过程当中踩了些坑,此次一块儿把以前 debug 的经验分享一下。git

generate_multiple_pod_projects 选项

以前 Cocoapods 会把每一个依赖做为 target 放到 Pods 项目里,但 xcodeproj 自己的编码不太能适应这种状况,在引入几十个 pod 的状况下,项目解析的效率会急剧降低。github

以我公司其中一个主项目为例,Pods 项目的大小达到了 5.2 MB(这可都是纯文本),在第一次打开项目,解析项目构建索引时,就能明显听到风扇开始狂转,这个过程会持续好几分钟才会结束。swift

Cocoapods 此次更新引入了一个 generate_multiple_pod_projects 的选项,可让每一个依赖都做为一个单独的项目引入,大大增长了解析速度:xcode

开启的方式很简单,只要在 Podfile 里加入这一行就能够了:ruby

install! 'cocoapods', generate_multiple_pod_projects: true
复制代码

拆分后每一个项目的大小都差很少是 40 - 100 kb 左右:多线程

这个选项开启以后的效果很是显著,我在 Xcode 里执行了 clean,以后 indexing 的过程在几秒钟里就结束了,并且风扇也没有狂转。函数

至于为何这样能够提高项目的解析速度,我大概看了一下 xcodeproj 的编码,全部的 Item 都会按照类别存放到各自的 section 里,最终在项目的结构树里会以引用的形式呈现。工具

因此文件引用查找的范围是全部 Pod 引用库的文件的集合,而每次索引的构建都至少会遍历一次项目树,这就会致使索引时间的暴增,除此以外单个庞大的项目解析也不利于多线程执行,拆分红多个项目的话就能有效地解决这些问题。post

install! 函数只能调用一次

须要注意 install! 是个用来配置的函数,因为以前我还开启了另外一个选项,因此接入时是这么作的:ui

install! 'cocoapods', generate_multiple_pod_projects: true
install! 'cocoapods', disable_input_output_paths: true
复制代码

可是这么作以后发现不生效,后来才想起来 install! 是一个用来配置的函数,重复调用的话,只会以最后一次的调用为准。因此应该在一次调用里把它们都传入进去:

install! 'cocoapods', 
         disable_input_output_paths: true,
         generate_multiple_pod_projects: true
复制代码

Swift 版本控制

另外一个坑就是在 post_install 时,为了一些版本的兼容,须要遍历全部 target,调整一部分库的 Swift 版本:

post_install do |installer|

  swift_4_0_compatible = [ ... ]
  swift_4_2_compatible = [ ... ]

  installer.pod_targets.each do |t|
    t.build_configurations.each do |c|
      c.build_settings['SWIFT_VERSION'] = '4.0' if swift_4_0_compatible.include? t.name
      c.build_settings['SWIFT_VERSION'] = '4.2' if swift_4_2_compatible.include? t.name
    end
  end
end
复制代码

可是若是开启了 generate_multiple_pod_projects 的话,因为项目结构的变化,installer.pod_targets 就没办法得到全部 pods 引入的 target 了。

Podfile 里的代码如何 debug

查了 Xcodeproj 和 Cocoapods 的文档以后我都没有获得很好的解答,因此我就想用 xcodeproj 自己的接口去处理这件事情。

因为 Podfile 本质上是 Ruby 脚本,因此这里我一般会使用 Ruby 的 debugger 去操做,经过 Ruby 强大的自省能力,在 debugger 里进行尝试而后找到咱们须要的接口,开始以前咱们须要安装一个 Ruby 的工具,步骤以下:

  1. 首先是安装 debugger gem install pry
  2. 接着在 Podfile 的开头导入 require 'pry'
  3. 而后在咱们想要插入断点的地方插入 binding.pry 语句就能够了

查找能用的接口

我在 post_install 里插入了断点,接着运行 pod install,就看到断点生效了:

Ruby 的自省能力很是强大,并且 pry 也基于此作了不少实用的功能,在这里我直接输入了 installer 回车,就能看到它全部属性都被递归打印出来。

这里面我找了一下以后,发现一个文档里没有记录的属性,叫作 pod_target_subprojects,包含了全部 Pods 的项目,彷佛能够知足咱们的需求:

接着 Ctrl + d 退出 pry,回到 Podfile 修改便可:

post_install do |installer|

  swift_4_0_compatible = [ ... ]
  swift_4_2_compatible = [ ... ]

  installer.pod_target_subprojects.flat_map { |p| p.targets }.each do |t|
    t.build_configurations.each do |c|
      c.build_settings['SWIFT_VERSION'] = '4.0' if swift_4_0_compatible.include? t.name
      c.build_settings['SWIFT_VERSION'] = '4.2' if swift_4_2_compatible.include? t.name
    end
  end
end
复制代码

最后 pod install 一下,打开 Xcode 查看对应的 target 的编译设置,确实有效。

这里介绍的 debug 方法在 fastlane 里也适用,很是建议你们在编写复杂脚本时先用 debugger 去提早踩坑。

结语

用惯了 Ruby 的 debug 方式以后,回到 LLDB 感受体验差了不少😂。

若是以为文章还不错的话能够关注一下个人博客

相关文章
相关标签/搜索