日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

iOS之深入解析CocoaPods的插件机制和如何加载插件整合开发工具

發(fā)布時間:2024/5/28 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS之深入解析CocoaPods的插件机制和如何加载插件整合开发工具 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、CocoaPods 插件機制

① Ruby

  • 在 Ruby 中,類永遠是開放的,總是可以將新的方法加入到已有的類中,除了自己的代碼中,還可以用在標準庫和內置類中,這個特性被稱為 Ruby Open Classes。
  • 自定義一個類 Human,放在 human.rb 文件中:
class Humandef greeting puts "hello everybody"enddef hungry puts "I am hungry"end end
  • 新增一個main.rb:
require_relative 'human'john = Human.newjohn.greeting # hello everybodyjohn.hungry # I am hungry
  • 再在 main.rb 中重新定義 hungry 方法:
class Humandef hungry puts "I could eat a horse"end endjohn.hungry # I could eat a horse
  • 可以看到,在新增 hungry 方法之后,所有的 Human 類的實例均調用新的實現(xiàn),即使是已經(jīng)創(chuàng)建好的實例,這里故意放到兩個文件中是想說明這個特性是可以跨文件甚至跨模塊的,對 Ruby 內置方法的替換也是可以的(謹慎使用)。
puts "hello".sizeclass String def sizeputs "goodbye"end end# 5 # goodbye puts "hello".size
  • 這個特性是十分強大的,讓我們可以很容易的對三方模塊進行擴展,也是 Cocoapods 的插件體系所依賴的基礎。

② CocoaPods 流程分析

  • 首先,Cocoapods 提供了一個便捷的命令行工具庫 CLAide,CLAide 包含很多功能,例如,一套命令基類,一套插件加載機制等。
  • Command 基類在 lib/claide/command.rb 中,提供了大量基礎功能,包括 run 、 options、 help 等。當每次執(zhí)行 pod xxx 命令時候,會執(zhí)行 bin 目錄下的可執(zhí)行文件 pod:
require 'cocoapods'if profile_filename = ENV['PROFILE']# 忽略不相關內容... elsePod::Command.run(ARGV) end
  • 這里實際上是 Pod 模塊從 CLAide 繼承子類 Command < CLAide::Command,執(zhí)行 Pod 命令時候,就會調用:
def self.run(argv)help! 'You cannot run CocoaPods as root.' if Process.uid == 0verify_minimum_git_version!verify_xcode_license_approved!super(argv) ensureUI.print_warnings end
  • 實際上只是擴展了一些檢測 git 版本、Xcode 證書等,真正核心部分還是調用的 CLAide 的實現(xiàn):
def self.run(argv = [])plugin_prefixes.each do |plugin_prefix|PluginManager.load_plugins(plugin_prefix)endargv = ARGV.coerce(argv)command = parse(argv)ANSI.disabled = !command.ansi_output?unless command.handle_root_options(argv)command.validate!command.runend rescue Object => exceptionhandle_exception(command, exception) end
  • 可以看到這里真正執(zhí)行命令之前會遍歷所有的插件前綴,并進行插件加載,回頭來再查看 cocoapods/command.rb 會發(fā)現(xiàn),這里指定了約定的插件前綴:
self.plugin_prefixes = %w(claide cocoapods)
  • 可以看到這里的插件分為兩種,我們目前只關心文件名為 CocoaPods 前綴的插件。深入 PluginManager 的具體實現(xiàn)看下:
def self.load_plugins(plugin_prefix)loaded_plugins[plugin_prefix] ||=plugin_gems_for_prefix(plugin_prefix).map do |spec, paths|spec if safe_activate_and_require(spec, paths)end.compact enddef self.plugin_gems_for_prefix(prefix)glob = "#{prefix}_plugin#{Gem.suffix_pattern}"Gem::Specification.latest_specs(true).map do |spec|matches = spec.matches_for_glob(glob)[spec, matches] unless matches.empty?end.compact enddef self.safe_activate_and_require(spec, paths)spec.activatepaths.each { |path| require(path) }true# 不相關代碼略去# ... end
  • 只分析核心相關代碼,整體的流程大致是:
    • 調用 PluginManager.load_plugins 并傳入插件前綴;
    • PluginManager.plugin_gems_for_prefix 對插件名進行處理,取出需要加載的文件,例如 CocoaPods 前綴在這里會轉換為所有包含 cocoapods_plugin.rb 的 gem spec 信息及文件信息,例如 ~/cocoapods-qt/lib/cocoapods_plugin.rb;
    • 調用 PluginManager.safe_activate_and_require 進行對應的 gem spec 檢驗并對每個文件進行加載。

③ Cocoapods-plugins

  • 執(zhí)行 pod plugins create cocoapods-test 之后,發(fā)現(xiàn)自動創(chuàng)建了一個 gem 工程,其中的 lib 文件夾下果然存在一個 cocoapods_plugin.rb 文件,整體的目錄結構如下:
├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── cocoapods-test.gemspec ├── lib │ ├── cocoapods-test │ │ ├── command │ │ │ └── test.rb │ │ ├── command.rb │ │ └── gem_version.rb │ ├── cocoapods-test.rb │ └── **cocoapods_plugin.rb** └── spec├── command│ └── test_spec.rb└── spec_helper.rb
  • 這里最核心的就是 cocoapods_plugin.rb,前面分析過,執(zhí)行 pod 命令時候會主動加載所有 cocoapods_plugin.rb 文件,那么只要將需要擴展的類加到這里面,執(zhí)行命令時候就會生效:
class Test < Commandself.summary = 'Short description of cocoapods-test.'self.description = <<-DESCLonger description of cocoapods-test.DESCself.arguments = 'NAME'def initialize(argv)@name = argv.shift_argumentsuperenddef validate!superhelp! 'A Pod name is required.' unless @nameenddef runUI.puts "Add your implementation for the cocoapods-test plugin in #{__FILE__}"end end
  • 可以看到只是新增了一個 Test 命令,并加了一些描述信息。為了擴展能生效,可以通過幾種方式:
    • 本地 gem 源碼依賴;
    • 安裝 gem 產物。
  • 為了更貼近實際生產發(fā)布流程,可以采用第二種方式:
    • 首先,編譯生成 gem 產物:
gem build cocoapods-test.gemspec
    • 其次,本地安裝:
gem install ~/CocoapodsQt/cocoapods-test/cocoapods-test-0.0.1.gem --local
    • 再執(zhí)行 pod 命令:

  • 可以看到擴展的命令已經(jīng)生效,接下來就可以開始愉快的 coding。

二、CocoaPods 如何加載插件?

  • CocoaPods 為開發(fā)者提供了插件注冊功能,可以使用 pod plugins create NAME 命令創(chuàng)建插件,并在 Podfile 中通過 plugin ‘NAME’ 語句引入插件。雖然在一般情況下很少使用這個功能,但在某些場景下,利用插件能比較方便快捷地解決問題,比如清除 input,output 文件、創(chuàng)建 Podfile DSL 等。
  • 首先,由于 pod install 過程會涉及到插件的加載,因此直接查看 installer.rb 文件:
# Runs the registered callbacks for the plugins post install hooks. # def run_plugins_post_install_hookscontext = PostInstallHooksContext.generate(sandbox, aggregate_targets)HooksManager.run(:post_install, context, plugins) end# Runs the registered callbacks for the plugins pre install hooks. # # @return [void] # def run_plugins_pre_install_hookscontext = PreInstallHooksContext.generate(sandbox, podfile, lockfile)HooksManager.run(:pre_install, context, plugins) end# Ensures that all plugins specified in the {#podfile} are loaded. # # @return [void] # def ensure_plugins_are_installed!require 'claide/command/plugin_manager'loaded_plugins = Command::PluginManager.specifications.map(&:name)podfile.plugins.keys.each do |plugin|unless loaded_plugins.include? pluginraise Informative, "Your Podfile requires that the plugin `#{plugin}` be installed. Please install it and try installation again."endend end
  • 其中 run_plugins_pre_install_hooks 和 run_plugins_post_install_hooks 分別執(zhí)行插件注冊的 pre_install 和 pod_install 方法, ensure_plugins_are_installed 則確認插件是否已被安裝。
  • 接下來看下 Command::PluginManager,這個類在 claide/command/plugin_manager 文件內,屬于 claide gem:
# @return [Array<Gem::Specification>] Loads plugins via RubyGems looking # for files named after the `PLUGIN_PREFIX_plugin` and returns the # specifications of the gems loaded successfully. # Plugins are required safely. # def self.load_plugins(plugin_prefix)loaded_plugins[plugin_prefix] ||=plugin_gems_for_prefix(plugin_prefix).map do |spec, paths|spec if safe_activate_and_require(spec, paths)end.compact end# @group Helper Methods# @return [Array<[Gem::Specification, Array<String>]>] # Returns an array of tuples containing the specifications and # plugin files to require for a given plugin prefix. # def self.plugin_gems_for_prefix(prefix)glob = "#{prefix}_plugin#{Gem.suffix_pattern}"Gem::Specification.latest_specs(true).map do |spec|matches = spec.matches_for_glob(glob)[spec, matches] unless matches.empty?end.compact end# Activates the given spec and requires the given paths. # If any exception occurs it is caught and an # informative message is printed. # # @param [Gem::Specification] spec # The spec to be activated. # # @param [String] paths # The paths to require. # # @return [Bool] Whether activation and requiring succeeded. # def self.safe_activate_and_require(spec, paths)spec.activatepaths.each { |path| require(path) }true rescue Exception => exception # rubocop:disable RescueExceptionmessage = "\n---------------------------------------------"message << "\nError loading the plugin `#{spec.full_name}`.\n"message << "\n#{exception.class} - #{exception.message}"message << "\n#{exception.backtrace.join("\n")}"message << "\n---------------------------------------------\n"warn message.ansi.yellowfalse end
  • 以上代碼調用幾個的 Gem::Specification 方法如下:
# 獲取最新 spec 集合 # Return the latest specs, optionally including prerelease specs if prerelease is true. latest_specs(prerelease = false) # 獲取 gem 中匹配的文件路徑 # Return all files in this gem that match for glob. matches_for_glob(glob) # 激活 spec,注冊并將其 lib 路徑添加到 $LOAD_PATH ($LOAD_PATH 環(huán)境變量存儲 require 文件時查找的路徑) # Activate this spec, registering it as a loaded spec and adding it's lib paths to $LOAD_PATH. Returns true if the spec was activated, false if it was previously activated. Freaks out if there are conflicts upon activation. activate()
  • 可以看到在 loaded_plugins[plugin_prefix] 為空的情況下,程序會執(zhí)行 plugin_gems_for_prefix 方法,plugin_gems_for_prefix 方法通過 latest_specs 獲取了最新的 spec,并通過 spec 的 matches_for_glob 方法對文件進行匹配,當 spec 中存在匹配 “#{prefix}_plugin#{Gem.suffix_pattern}” 格式的文件時,則視其為 CocoaPods 插件。在拿到插件及其匹配文件后,safe_activate_and_require 方法將文件加入 $LOAD_PATH 中并 require 之。
  • 另外 CLAide::Command 類會在 run 類方法中加載所有插件,然后根據(jù)解析后的信息,執(zhí)行對應的命令:
# @param [Array, ARGV] argv # A list of (remaining) parameters. # # @return [Command] An instance of the command class that was matched by # going through the arguments in the parameters and drilling down # command classes. # def self.run(argv = [])plugin_prefixes.each do |plugin_prefix|PluginManager.load_plugins(plugin_prefix)endargv = ARGV.coerce(argv)command = parse(argv)ANSI.disabled = !command.ansi_output?unless command.handle_root_options(argv)command.validate!command.runend rescue Object => exceptionhandle_exception(command, exception) end
  • 對于通過 pod plugin create 命令創(chuàng)建的插件來說,lib 目錄下都會自動生成一個 cocoapods_plugin.rb 文件,這個文件就是用來標識此 gem 為 CocoaPods 插件的。
  • 如果想手動創(chuàng)建 CocoaPods 插件,需要滿足以下兩個條件:
# Handles plugin related logic logic for the `Command` class. # # Plugins are loaded the first time a command run and are identified by the # prefix specified in the command class. Plugins must adopt the following # conventions: # # - Support being loaded by a file located under the # `lib/#{plugin_prefix}_plugin` relative path. # - Be stored in a folder named after the plugin.# - 支持通過 `lib/#{plugin_prefix}_plugin` 路徑的文件加載 # (也就是說,如果要對外暴露插件內部存的方法,需要在此文件中 require 之,比如自定義的 Podfile DSL 文件) # - 保存在以插件命名的文件夾中
  • 在 CocoaPods 上下文中,以上的 plugin_prefix 如下:
self.plugin_prefixes = %w(claide cocoapods)
  • 如果需要外部 gem 以插件的形式提供某些功能,可以通過和 CocoaPods 一樣的方式實現(xiàn),即規(guī)定特定的命名規(guī)則,然后通過 Gem::Specification 提供的方法獲取滿足條件的 gem,再 require 入口文件:
spec = Gem::Specification.find_by_name('naruto') spec.activate matches = spec.matches_for_glob('naruto') matches.each do |path|require(path) end

三、CocoaPods 插件整合開發(fā)工具

① Podfile 內聲明公有源和私有源 source

  • 如果組件化采用公有源和私有源雙源的方案,為了 pod install 命令能夠找到公有組件和私有組件,需要在 Podfile 里指定雙源地址,如:
# 私有源地址 source 'https://xyz.com/ios/pod-specs.git' # 公有源地址 source 'https://github.com/CocoaPods/Specs.git'
  • 但存在以下問題:
    • 如果公司項目存在多個 APP,每個工程都要配置這樣兩行,各組件 Example 工程也存在這樣的問題;
    • 如果公司 git 換過地址,每次都要更換各個工程里的地址,且導致歷史 tag 工程 pod install 失敗;
    • 新電腦需要手動添加私有源才能工作。
  • 這次新建 cocoapods-lebby 插件工程,就通過 CocoaPods 提供的 source_provider hook 時機添加 source 來統(tǒng)一管理源地址,源不存在時可自動添加,注冊插件如下:
Pod::HooksManager.register('cocoapods-lebbay', :source_provider) do |context|sources_manager = Pod::Config.instance.sources_managercontext.add_source(sources_manager.private_source)context.add_source(sources_manager.public_source) end
  • 閉包參數(shù) context 對象提供了 add_source 方法用于添加 source 對象,這里借鑒 CocoaPods 源碼做法,給 Pod::Source::Manager 擴展了兩個方法分別提供私有源和公有源:
module Podclass Sourceclass Manager# 私有源 sourcedef private_sourceurl = 'https://xyz.com/ios/pod-specs.git'source = source_with_url(url)return source if sourceCommand::Repo::Add.parse(['lebbay-spec', url, 'master']).runsource_with_url(url)end# 公有源 sourcedef public_sourceurl = 'https://github.com/CocoaPods/Specs.git'source = source_with_url(url)return source if sourceCommand::Repo::Add.parse(['master', url, 'master']).runsource_with_url(url)endendend end

② Podfile 內提供 dev_pods 自定義方法用于提測過程中實時拉取組件分支最新 commit

  • 在組件開發(fā)過程中經(jīng)常會修改幾個 pod 的代碼,需要一個個的將 pod 指向本地開發(fā)目錄,在項目測試過程中又要將 pod 一個個指向提測分支,比如:
# 開發(fā)階段 pod 'PodA', :path => '../PodA' pod 'PodB', :path => '../PodB'# 測試階段 pod 'PodA', :git => 'https://xyz.com/ios/PodA.git', :branch => 'release/1.0.0' pod 'PodB', :git => 'https://xyz.com/ios/PodB.git', :branch => 'release/1.0.0'
  • 為了簡化寫法,我們提供了 dev_pods 方法,簡化邏輯后思路大致如下:
def dev_pods(pods, branch = '') if branch.length > 0# 測試階段pods.each do |name|pod name, :git => "https://xyz.com/ios/#{name}.git", :branch => "#{branch}"endelse# 開發(fā)階段development_path = File.read('./bin/.development_path').chomppods.each do |name|pod name, :path => "#{development_path}#{name}"endend end
  • 在 ./bin/.development_path 文件里配置本地開發(fā)目錄,dev_pods 方法的用法如下:
# 開發(fā)階段 dev_pods ['PodA', 'PodB']# 測試階段 dev_pods ['PodA', 'PodB'], 'release/1.0.0'
  • 在測試階段還有一個問題是,我們希望在組件的提測分支上修改了 bug、提交 commit 之后主工程 pod install 即可拉取最新代碼。但因為 Podfile.lock 文件的存在,pod install 之后會把 commit 節(jié)點記下來,除非在提交 pod 改動后,再去更新主工程的 Podfile.lock 文件,否則是不會拉取最新代碼的。為了實現(xiàn)這一需求,在 dev_pods 方法里修改了 Podfile.lock 文件,刪掉 commit 節(jié)點信息,這樣在拉取對應 pod 組件的時候就會拉取最新代碼了。
  • 在應用過程中發(fā)現(xiàn)的另一問題是:tag 沖突,當組件 PodA 指向的 release/1.0.0 分支里 podspec 里的版本號是 0.0.9,那么主工程的 Podfile.lock 文件里記錄的就是 0.0.9。當測試完成,組件 podA 發(fā)版修改版本號為 1.0.0 并提交到了 release/1.0.0 分支里,這時主工程再執(zhí)行 pod install 就會報 tag 沖突。為解決這一問題,避免提測組件版本號變更影響主工程提測打包,可以的做法是如果 PodA 通過 dev_pods 方法指向了分支,那么在 dev_pods 里刪掉 PodA 在 Podfile.lock 里的記錄(只刪除 version、branch、commit 信息即可),這樣在 pod install 的時候就會像下載一個新的 pod 一樣。
  • 問題、需求及解決思路大致如上,在以前的方案是寫個 ruby 文件(lebbay.rb) 放在主工程目錄,在 Podfile 里 require ‘./bin/lebbay.rb’,修改 Podfile.lock 文件也是腳本遍歷文件內容操作字符串,現(xiàn)在統(tǒng)一整合到 cocoapods-lebbay 插件里,為 Podfile 擴充 DSL 方法,修改 Podfile.lock 文件可以直接使用 cocoapods-core 提供的 Lockfile 類及其方法:
module Podclass Podfilemodule DSLpublicdef dev_pods(pods, branch = '')if branch.length > 0pods.each do |name|pod name, :git => "https://xyz.com/ios/#{name}.git", :branch => "#{branch}"endpull_latest_code_and_resolve_conflict(pods)puts "lebbay: using remote pods with branch: #{branch}".greenelse# 自定義開發(fā)目錄development_path = Config.instance.dev_pods_pathpods.each do |name|pod name, :path => "#{development_path}#{name}"endputs "lebbay: using local pods with path: #{development_path}xxx".greenendend#--------------------------------------#privatedef pull_latest_code_and_resolve_conflict(pods)# 1、Podfile.lockrewrite_lock_file(pods, Config.instance.lockfile_path)# 2、Manifest.lockrewrite_lock_file(pods, Config.instance.sandbox.manifest_path)enddef rewrite_lock_file(pods, lock_path)return unless lock_path.exist?lock_hash = Lockfile.from_file(lock_path).to_hash# 1、PODSlock_pods = lock_hash['PODS']if lock_podstarget_pods = []lock_pods.each do |pod|if pod.is_a? Hashfirst_key = pod.keys[0]first_value = pod.values[0]if (first_key.is_a? String) && (first_value.is_a? Array)next if is_include_key_in_pods(first_key, pods)dep_pods = first_value.reject { |dep_pod| is_include_key_in_pods(dep_pod, pods) }target_pods << (dep_pods.count > 0 ? {first_key => dep_pods} : first_key)nextendelsif pod.is_a? Stringnext if is_include_key_in_pods(pod, pods)endtarget_pods << podendlock_hash['PODS'] = target_podsend# 2、DEPENDENCIESlocak_dependencies = lock_hash['DEPENDENCIES']if locak_dependenciestarget_dependencies = []locak_dependencies.each do |dependence|if dependence.is_a? Stringnext if is_include_key_in_pods(dependence, pods)endtarget_dependencies << dependenceendlock_hash['DEPENDENCIES'] = target_dependenciesendLockfile.new(lock_hash).write_to_disk(lock_path)enddef is_include_key_in_pods(target_key, pods)pods.each do |pod|if target_key.include? podreturn trueendendreturn falseend#--------------------------------------#end end end
  • 我們同時修改了 Pods/ 文件夾下的 Manifest.lock 文件,是因為 CooaPods 在 pod install 過程中會對比 lock 文件里記錄的 version 版本號,若 Manifest.lock 文件里記錄的版本沒變的話,在執(zhí)行 pod install 時 Pods/ 文件夾里對應 Pod 的代碼很可能是不會更新的。其中關于開發(fā)目錄(development_path = Config.instance.dev_pods_path),給 Pod::Config 擴展了兩個方法:設置開發(fā)目錄 & 讀取開發(fā)目錄:
module Podclass Config# 讀取目錄def dev_pods_pathconfig_path_file = dev_pods_path_config_filedev_path = File.read(config_path_file).chompend# 設置目錄def config_dev_pods_path(dev_path)raise Informative, "input can't be nil" unless dev_path.length > 0dev_path += '/' unless dev_path[dev_path.length - 1] == '/'config_path_file = dev_pods_path_config_fileFile.open(config_path_file, "w") do |file|file.syswrite(dev_path)endend# 配置文件def dev_pods_path_config_fileconfig_path = File.expand_path('~/.cocoapods-lebbay')FileUtils.makedirs(config_path) unless File.exists?config_pathconfig_path_file = config_path + '/dev_pods_path_config'unless File.exist?(config_path_file)File.open(config_path_file, "w") do |file|file.syswrite('../../')endendconfig_path_fileendend end
  • 給 pod 擴展了兩個方法入口分別執(zhí)行這倆方法,讀取開發(fā)目錄(pod dev-pods-path cat),設置開發(fā)目錄(pod dev-pods-path set):
require 'cocoapods-lebbay/cache_config'module Podclass Commandclass DevPodsPath < Commandself.abstract_command = trueself.summary = 'set or cat dev_pods path'def self.options[]endendclass Set < DevPodsPathself.summary = 'set dev_pods path'def runUI.puts "Please input dev_path for dev_pods command:".greenanswer = STDIN.gets.chomp.stripConfig.instance.config_dev_pods_path(answer)endendclass Cat < DevPodsPathself.summary = 'cat dev_pods path'def runUI.puts Config.instance.dev_pods_path.greenendendend end

③ 解決 libwebp 網(wǎng)絡問題:修改公有源里 podspec git 地址為 github 地址

  • 這個問題因為 libwebp 的 podspec 里 git 地址是:https://chromium.googlesource.com/webm/libwebp,在 pod install 的時候大概率會因為網(wǎng)絡原因而下載失敗,將其改為:https://github.com/webmproject/libwebp.git 即可。
  • 之前的做法是在 lebbay.rb 腳本里提供了 libwep_spec_fix 方法批量修改公有源里 libwebp.podspec 的 git 地址,然后在 Podfile 文件里調用下這個方法,現(xiàn)在也整合到了 cocoapods-lebbay 插件里,在 pre_install 的 hook 時機里執(zhí)行:
Pod::HooksManager.register('cocoapods-lebbay', :pre_install) do |context|target_url = "https://chromium.googlesource.com/webm/libwebp"replace_url = "https://github.com/webmproject/libwebp.git"repo_path = File.expand_path('~/.cocoapods/repos/master/Specs/1/9/2/libwebp/*/*.json') Dir.glob(repo_path) do |json_file|json_text = File.read(json_file)json_text = json_text.gsub(target_url, replace_url)File.open(json_file, "w") do |file|file.syswrite(json_text)endend end

④ 解決 CocoaPods bug:一旦有任一組件在 podspec 里使用 resources 命令管理資源文件,CocoaPods 會把所有組件內的資源文件拷貝到 main bundle 里

  • 關于這個問題的具體信息請查看:If there are one pod using xcassets via resources spec syntax, then all xcassets will be copied and compied twice during [CP] Copy Pods Resources build phase #8431,雖然目前沒有 pod 在使用 resources 命令,但為了避免三方庫會引入這個問題,還是需要左規(guī)避,在 post_install 的 hook 時機里修復 CocoaPods 的腳本,之前是將 post_install 的 hook 寫在了 Podfile 里,現(xiàn)在放在了插件里來做:
Pod::HooksManager.register('cocoapods-lebbay', :post_install) do |context|target_label = context.umbrella_targets.first.cocoapods_target_labelsystem %Q{sed -i "" "s/\\[\\[ \\$line != \\"\\${PODS_ROOT}\\*\\" \\]\\]/\\[\\[ \\$line != \\${PODS_ROOT}\\* \\]\\]/g" "./Pods/Target Support Files/#{target_label}/#{target_label}-resources.sh"} end# before #if [[ $line != "${PODS_ROOT}*" ]]; then # changed #if [[ $line != ${PODS_ROOT}* ]]; then

⑤ 使用

  • 做完這些,各個工程里的 Podfile 文件就清爽了很多,之后再有需求的話也可以在 cocoapods-lebbay 插件里統(tǒng)一管理,可以很方便用戶安裝和命令維護,只需在 Podfile 里添加這樣一行,即可全部實現(xiàn):
plugin 'cocoapods-lebbay'

總結

以上是生活随笔為你收集整理的iOS之深入解析CocoaPods的插件机制和如何加载插件整合开发工具的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。