编译时自动Pod Install的实现

测试环境:
  • Cocoapods 1.3.1
  • Xcode8.3.3
实现说明:

在使用Cocoapods的过程中,我们经常会遇到过这种报错信息:‘error: The sandbox is not in sync with the Podfile.lock. Run ‘pod install’ or update your CocoaPods installation.’, 接着我们会到podfile所在的目录下执行pod install命令。但是今天
我突发奇想,想要实现能够自动执行pod install的功能。

刚开始以为很简单:只需要在[CP] Check Pods Manifest.lock脚本前插入一段脚本,该脚本用于对项目中Pods的依赖变更进行一个预检测,也就是和[CP] Check Pods Manifest.lock的一样,与pods提供的脚本不同的是,检测到不同步后不是报错而是直接执行pod install。(注:不能直接修改[CP] Check Pods Manifest.lock脚本,因为每次pod install都会重置这个脚本的内容)。

按照上面的想法,便试着在[CP] Check Pods Manifest.lock之前添加了一段脚本(Run Script Phase),然后问题出现了,执行完pod install后,Cocoapods会自动将自己的[CP] Check Pods Manifest.lock脚本置于所有````Run Script Phase```中的第一个位置。
所以这种办法就行不通了(因为Cocoapods会先检测然后报错)。

之后又想到官方提供的pod hook范例:

post_install do |installer|
  #自定义逻辑
end

可以hook的点就这一个,那就得想办法通过installer这个对象找到操作宿主项目配置的方法。然后给宿主项目相应的target
添加一个Run Script Phase,这样应该就能保证此时添加的脚本会置于Cocoapods添加的脚本之前。可是打印了installer的所有方法,并没有发现看起来像能够编辑宿主项目配置的(就算能找到这也不算个简单的方法),所有方法如下:

 [:update, :sandbox, :podfile, :lockfile, :repo_update?, :repo_updat
e, :repo_update=, :update=, :install!, :use_default_plugins, :use_d
efault_plugins?, :prepare, :resolve_dependencies, :download_depende
ncies, :installation_options, :aggregate_targets, :pod_targets, :an
alysis_result, :pods_project, :names_of_pods_to_install, :installe
d_specs, :development_pod_targets, :use_default_plugins=, :installe
d_specs=, :installation_options=, :config, :to_yaml, :to_yaml_prope
rties, :try, :try!, :blank?, :present?, :presence, :to_param, :to_q
uery, :psych_to_yaml, :to_json, :instance_of?, :kind_of?, :is_a?,
:tap, :public_send, :suppress, :class_eval, :remove_instance_variab
le, :singleton_method, :quietly, :suppress_warnings, :instance_vari
able_set, :define_singleton_method, :method, :public_method, :silen
ce_stream, :extend, :with_warnings, :silence_stderr, :capture, :t
o_enum, :enum_for, :enable_warnings, :silence, :<=>, :===, :=~,
:!~, :eql?, :respond_to?, :freeze, :inspect, :object_id, :send, :di
splay, :to_s, :silence_warnings, :nil?, :hash, :class, :singleton_c
lass, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust,
:untrusted?, :trust, :frozen?, :methods, :singleton_methods, :prote
cted_methods, :private_methods, :public_methods, :instance_variabl
e_get, :instance_variables, :instance_variable_defined?, :!, :==,
:!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

既然通过installer不行,那我们直接编辑项目配置文件,不通过Cocoapods提供的上下文对象,只使用Cocoapods提供的hook点,编辑项目配置文件使用Xcodeproj这个库(Cocoapods内部用于编辑项目配置文件的库),但是这样可能会有个问题:我们是在pod hookpod install过程中被执行的,那我们对项目的配置文件的修改可能会和Cocoapods的修改冲突,虽然个人感觉这种方式可能不行,但是还是尝试了下,上代码:

 require 'xcodeproj'
path_to_project = "xxxxxxxx/xxxx/MainPrj.xcodeproj"
project = Xcodeproj::Project.open(path_to_project)
main_target = project.targets.first
curPhases = main_target.build_phases
checkPhasesName = "checkAndAutoPodInstall"
checkPhasesIndex = -1
curPhases.each_index { |index|
    item = curPhases[index]
    if item.instance_of? Xcodeproj::Project::Object::PBXShellScriptBuildPhase and item.name == checkPhasesName
        checkPhasesIndex = index
        break 
    end
}
if checkPhasesIndex == -1
  puts "\033[32m CheckPhasesInject-add \033[0m\n"
  shellPhases = Xcodeproj::Project::Object::PBXShellScriptBuildPhase.new(project,project.generate_uuid())
  shellPhases.name = checkPhasesName
  shellPhases.shell_script = "echo 111"
  shellPhases.shell_path = "/bin/sh"
  curPhases.insert(0,shellPhases)
  project.save()
elsif checkPhasesIndex != 0
  puts "\033[32m CheckPhasesInject-switch \033[0m\n"
  checkPhases = curPhases.delete_at(checkPhasesIndex)
  curPhases.insert(0,checkPhases)
  project.save()
else puts "\033[32m CheckPhasesInject-do noting \033[0m\n"
end
大致说明一下这段代码:

这段脚本是在pod hook中执行的。

MainPrj是宿主项目。

checkAndAutoPodInstall则是需要优先于[CP] Check Pods Manifest.lock执行的Run Script Phase的名称。

pod hook执行时判断宿主项目的主Target的Build Phases中是否有checkAndAutoPodInstall脚本,没有则
添加一个并设置到所有Run Script Phase中的第一个。但是后面测试发现,在位置上还是会有问题:
如果已经添加过checkAndAutoPodInstall,那么pod hook就不会修改项目配置,此时Cocoapods会把[CP] Check Pods Manifest.lock置为第一个位置。但是如果checkAndAutoPodInstall没有添加过,而是在pod hook中添加的就不会有这个问题。基于此,那么可以得到这样一个方案: pod hook中每次都先把checkAndAutoPodInstall删除,然后再新增。
这个方案虽然能解决目前讨论的自动Pod Install的问题,但是会出现项目代码版本管理问题:即使项目未做任何改动,每次pod Install后项目配置文件都会改变,这是不可接受的,所以最终此方案只能放弃。

接着再想其他办法,注意到Target Dependencies,这个每次编译过程中都是第一个处理的,既然如此,那就可以
新建一个target,然后在新建的target中添加Cocoapods检测脚本,最终,通过这种形式实现了Pod Install的自动执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值