赞
踩
在使用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 hook
是pod 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的自动执行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。