Podfile 解析最佳实践
基本語法
首先需要做的是,看懂一個 Podfile。那么需要了解一些最基本的 ruby 語法,這部分非常簡單:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' pod 'FLEX', :configurations => ['Debug'], :branch => 'develop' use_frameworks!以上三行代碼是 Podfile 中最為常見的,其實這三行是在調(diào)用不同的方法。
方法調(diào)用
Ruby 中,方法調(diào)用的參數(shù)列表可以以空格形式接在方法名后,多個參數(shù)以逗號隔開,所以等價于:
source 'https://github.com/CocoaPods/Specs.git' # => source('https://github.com/CocoaPods/Specs.git')platform :ios, '8.0' # => platform(:ios, '8.0')如果是最后一個參數(shù)是字典,那么字典的大括號也可以省略,所以 pod 的調(diào)用等價于:
pod 'FLEX', :configurations => ['Debug'], :branch => 'develop' #=> map = {:configurations => ['Debug'],:branch => 'develop' } pod('FLEX', map)符號(Symbol)
Symbol 是 Ruby 中的一種對象類型,一般作為名稱標簽,為了不影響閱讀,我把 Symbol 的定義放在最后,這里可以暫且把它當(dāng)做前面加了 : 的 string。
所以,上面的代碼中,出現(xiàn)的 :ios,:configuration,:branch 以及常見的 :git,:tag 等都是 Symbol。
方法定義
Ruby 的方法定義更加靈活,語義也更加豐富。
方法名
比如 :nil?, empty?, merge! 這類方法。
方法名小寫,可包含 !,? 這類符號。用法可以學(xué)習(xí)系統(tǒng)的定義:
? 常用于判斷,取代了 is_ 開頭的定義習(xí)慣。
! 常用于需要注意的方法,比如 arr.merge!(other_arr) 表示合并到 arr;與之對應(yīng)的是 arr.merge(other_arr),表示合并,但不修改 arr,而是返回合并后的結(jié)果。
在很多開源庫中,! 的用法就比較巧妙,有可能并不表示在當(dāng)前對象上進行修改,僅僅為了優(yōu)雅好看也是可能的。
所以,Podfile 中出現(xiàn)的 use_frameworks! 也是在調(diào)用方法。
參數(shù)列表
為了簡單,這里僅介紹可空的參數(shù)定義。還是以 pod 方法舉栗子:
常見的 pod 調(diào)用如上,通過調(diào)用就能猜出 pod 方法的聲明:
# pname: 庫名 # version: 指定版本,且可空 # map: 用鍵值對接收其他參數(shù) def pod(pod_name, version = nil, **map)# ... end大致就是這樣,這里的 * 和指針沒關(guān)系 🌚。完整參數(shù)列表的定義方式,我寫在文末吧。
返回值
其實解析這部分用不上返回值,不過可以介紹一下。Ruby 返回值有以下幾個特點:
如果是最后一行,可以不寫 return。
支持多個返回值。
代碼塊(Block)
這個和 Objective-C 差不多,常用于回調(diào)。當(dāng)然 Podfile 也不缺少:
do…end 可以看成大括號,:Meitu 是 target 方法的第一個參數(shù)。綜合之前介紹的語法,target 的定義就呼之欲出了:
# tname: target 名稱 # block: 回調(diào) def target(tname, &block)# ...# 調(diào)用yield if block_given? end語法到這里就基本夠用了,接著介紹如何解析。
解析
既然 Podfile 中是 Ruby 代碼,也就表示,可以通過調(diào)用 Ruby 腳本的方式,直接執(zhí)行 Podfile。
ruby ~/Desktop/Podfile然后就報錯了…(編譯器又不知道 source,pod 這都是些什么方法…
定義方法
首先需要定義解析需要調(diào)用的方法,讓指定的變量乖乖的被對應(yīng)參數(shù)接收。最簡易的版本,需要實現(xiàn) target 和 pod 兩個方法:
target
工程可能對應(yīng)多個 target,具體要解析哪個 target,需要對應(yīng)到打包時指定的 target,所以采用外部傳入的方式:$target_argv:
def target(target_name = nil, &block = nil)# target name 可能是 String,可能是 Symbol,統(tǒng)一 to_s 一下# 如果不是當(dāng)前打包的 target,直接返回就行了return if target_name.to_s != $target_argv# 調(diào)用 blockyield if block_given? endpod
實現(xiàn) pod 以后,就可以通過參數(shù)讀取這種值了。同樣,pod 可能包含 configuration 信息,這也是需要對應(yīng)打包的 configuration 參數(shù)的:
def pod(pod_name, version = nil, **args)git = args[:git]branch = args[:branch]tag = args[:tag]commit = args[:commit]configurations = args[:configurations]# 如果 pod 指定了 configuration,則判斷是否包含當(dāng)前 configurationunless configurations.nil?return unless configurations.include?($configuration)end# 通過哪種方式引用,這里可以通過 tag、commit、branch 的 nil? 來判斷來源comes_from = "tag"# $map 為全局變量$map[pod_name] = {comes_from: comes_from,version: version} endmethod_missing
除了 target 和 pod 方法外,Podfile 中還存在 source、platform 等各種各樣的方法,一一實現(xiàn)是不可能的。對此,Ruby 提供了 method_missing 方法,該方法的作用類似于消息轉(zhuǎn)發(fā)。當(dāng)程序調(diào)用沒有實現(xiàn)的方法時,統(tǒng)一走 method_missing。
因為我們不需要處理未實現(xiàn)方法的邏輯,所以方法體是空的,不需要實現(xiàn)。
導(dǎo)出
到此,整個解析就已經(jīng)完成了,比起以前用正則寫的版本,清爽了很多。最后一步,將解析結(jié)果導(dǎo)出為 JSON 文件。代碼很簡單:
Podfile.lock
這里簡單提一下 lock 文件,因為 lock 文件中有準確的版本號,所以對應(yīng)引用版本都從 lock 當(dāng)中讀取。而 lock 文件其實是 yaml 格式的,可以通過 yaml 庫將它解析為 hash 和 array 進行讀取。
整個流程
那么,應(yīng)該如何將解析和導(dǎo)出兩個步驟串起來呢?方法需要定義在代碼開頭,導(dǎo)出需要放在代碼末尾,所以有了以下結(jié)構(gòu):
定義
eval(File.read(podfile_path))導(dǎo)出
這里用到了非常強大的 eval 函數(shù),也就是將 podfile 內(nèi)容讀取為將字符串并當(dāng)做代碼執(zhí)行。
ruby inject_template.rb target_name configuration_name result_path podfile_path🚣? 🚣 🚣? 🚣?
最后
Symbol
Symbol 是 Ruby 中最為基礎(chǔ)的對象類型,存儲在 Symbol Table 中,可以看做 name 和 ID 的對應(yīng)。Symbol 不可寫,地址不變,全局唯一。這和 String 不同,兩個值相同的 String,其實是不同的地址。
類似于 Java 的 String 和 static String,一個是用完重新分配,一個是始終是一個存儲單元。針對于這個特性,Symbol 的效率會比 String 高一些。常用于成員變量名,hash 的 key 等。
如果想繼續(xù)了解 Symbol,推薦閱讀:
Understanding Differences Between Symbols & Strings in Ruby
Ruby Symbols
官方文檔
方法定義
a:Positional argument,位置參數(shù)。也就是說,聲明在第一個,第一個傳入的就一定是 a 接收。
b:和 a 含義相同,且有默認值。
c:連續(xù)多個 Positional argument。
d:Keyword argument,對位置沒要求,接收指定 keyword 對應(yīng)的值。
e:和 d 含義相同,且有默認值。
f:連續(xù)多個 Keyword argument。
g:block。
總結(jié)
以上是生活随笔為你收集整理的Podfile 解析最佳实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电力系统matlab建模视频,MATLA
- 下一篇: python秒网课_利用python完成