目前大多數(shù)iOS應(yīng)用需要兼容到iOS8.0,那么問題來了,在測(cè)試設(shè)備不夠的情況下,我們只能使用模擬器來湊數(shù)進(jìn)行兼容性測(cè)試。但是iOS開發(fā)運(yùn)行流程對(duì)于開發(fā)者來說是正常操作,但是對(duì)于測(cè)試人員來說可能就有點(diǎn)難受了,尤其是某些情況下我們需要執(zhí)行pod install等前置操作。那么假設(shè)我們的測(cè)試人員不關(guān)心我們的代碼,也不關(guān)心應(yīng)用在運(yùn)行前需要做哪些準(zhǔn)備工作,我們?cè)撊绾巫龅揭绘I模擬器運(yùn)行app呢?本文以iPhone應(yīng)用為例來實(shí)現(xiàn)模擬器自動(dòng)構(gòu)建、自動(dòng)安裝、自動(dòng)啟動(dòng)的shell腳本,本文假設(shè)有個(gè)名稱和target都是“Apollo”的項(xiàng)目。
1.xcode運(yùn)行應(yīng)用
我們知道利用xcode利用模擬器運(yùn)行應(yīng)用就是Run按鈕一鍵或者是Command+R的事,但其實(shí)在底層這些操作都是觸發(fā)一系列shell腳本來構(gòu)建安裝啟動(dòng)模擬器和應(yīng)用。xcode安裝的同時(shí)提供了xcodebuild/xrun/instruments等工具,給我們的模擬器應(yīng)用自動(dòng)構(gòu)建提供思路。
2.思路1
異于真機(jī),模擬器安裝的應(yīng)用包并非是.ipa文件,而是.app文件,將.ipa文件解壓后得到文件夾Payload,里面正好有個(gè).app文件。那么這個(gè)是否就是我們所需要的呢,我們嘗試啟動(dòng)一個(gè)模擬器,然后將.app拖到模擬器屏幕內(nèi),發(fā)現(xiàn)安裝成功了,但是啟動(dòng)之后立即閃退。
其實(shí)閃退并非是因?yàn)?ipa內(nèi)的.app不能在模擬器運(yùn)行,而是ipa都是針對(duì)真機(jī)打出來的,如果項(xiàng)目中含有模擬器不能運(yùn)行的內(nèi)容自然就會(huì)閃退。
這里插一嘴,大部分靜態(tài)庫(kù),如果不支持模擬器運(yùn)行,我們都可以使用“#if TARGET_IPHONE_SIMULATOR”進(jìn)行屏蔽,那么在鏈接時(shí)就不會(huì)鏈接到包中,運(yùn)行時(shí)就不會(huì)閃退。
3.思路2
根據(jù)上面的經(jīng)驗(yàn),并不是所有的.ipa中的.app都能在模擬器中運(yùn)行,為了保險(xiǎn)起見中這種方式并不可用。
每次我們xocde編譯時(shí),都會(huì)生成一個(gè).app文件:

這個(gè)文件的位置在/Users/xxxx/Library/Developer/Xcode/DerivedData/xxxxxxx/Build/Products/Debug-iphonesimulator/xxxxx.app,我們可以右鍵Show in Finder查看。
我們將這個(gè).app拖到模擬器中安裝后發(fā)現(xiàn)啟動(dòng)還是閃退,原因是xcode編譯時(shí)選中的設(shè)備是Generic iOS Device,這也是真機(jī)。將設(shè)備切到模擬器后編譯重試,發(fā)現(xiàn)完美運(yùn)行,那么這個(gè).app就是我們想要的。
4.編譯腳本
根據(jù)以上的嘗試,我們基本確定了思路,就是需要以模擬器為設(shè)備編譯項(xiàng)目得到.app,并安裝到模擬器后啟動(dòng)。
第一步:使用編譯項(xiàng)目命令:
xcodebuild -workspace Apollo.xcworkspace -scheme Apollo -sdk iphonesimulator11.4 -configuration Debug
如果項(xiàng)目沒有集成cocoapods,請(qǐng)用-project。
這里插一嘴,可以使用man xcodebuild來查看文檔:

-sdk?iphonesimulator11.4意思就是以模擬器為設(shè)備編譯項(xiàng)目。那么這里如果不知道你的模擬器sdk版本,可以使用xcodebuild -showsdks查看支持的sdk:

第二步:?jiǎn)?dòng)一個(gè)模擬器:
crun instruments -w "iPhone 6 (9.0)" 或者?instruments -w "iPhone 6 (9.0)"
這里-w后面可以跟模擬器的名字,也可以是模擬器的id。
補(bǔ)充一句,兼容測(cè)試,前提是你機(jī)器上已經(jīng)下載了8.x,9.x,10.x,11.x版本的模擬器了:

如果你想查看本機(jī)instruments支持的模擬器名字、id等信息,請(qǐng)使用:instruments -w device

其中前面是名字,后面[]中間的是id(id不包括[])。
本人推薦使用名字不使用id,因?yàn)椴煌娔X的模擬器的id是不一樣的,甚至同一臺(tái)電腦登錄的不同兩個(gè)用戶看到的設(shè)備id也是不一樣的,但是名字可以是自定義的唯一的。而且,我也不推薦使用xcode自己生成的模擬器的名稱,為什么后面會(huì)講到。
第三步:將編譯生成的.app文件安裝到模擬器:
xcrun simctl install "iPhone 6 (9.0)" ~/Library/Developer/Xcode/DerivedData/Apollo-bepdsvfodytknjgsadpphjerbphz/Build/Products/Debug-iphonesimulator/Apollo.app
那么問題來了,這里的路徑是唯一的嗎?答案當(dāng)然不是,這里項(xiàng)目后面的長(zhǎng)字符創(chuàng)是xcode隨機(jī)生成的,目前我沒有找到更好的辦法,我嘗試過改變xcode默認(rèn)的編譯生成文件的位置,但是它仍然會(huì)生成這樣一個(gè)隨機(jī)文件夾名。但是有點(diǎn)好的是,同一個(gè)項(xiàng)目,只要編譯過一次,那么這個(gè)文件夾名就固定了,甚至你去刪除這個(gè)文件夾,xcode在下一次編譯時(shí)還會(huì)生成同樣名稱的文件夾,所以可以這么說,在同一電腦上,同一項(xiàng)目的編譯目錄是確定的。
這里的"iPhone 6 (9.0)"可以是模擬器名稱和模擬器id,或者直接使用booted安裝到啟動(dòng)的模擬器,但是我們可能同時(shí)啟動(dòng)多個(gè)模擬器,這種情況就不可控了,可以使用xcrun simctl list devices查看xcrun simctl支持的模擬器信息:

可以看到,xcrun simctl與instruments列出來的模擬器是有所不同的,xcrun simctl并不是以"iPhone (版本號(hào))"形式命名的。為了雙方統(tǒng)一名稱,我使用了xcrun simctl delete和xcrun simctl create來重新創(chuàng)建一套模擬器來使用:
xcrun simctl delete "iPhone 4s - 8.1";xcrun simctl create "iPhone 4s - 8.1" "com.apple.CoreSimulator.SimDeviceType.iPhone-4s" "com.apple.CoreSimulator.SimRuntime.iOS-8-1";
先嘗試刪除該名稱模擬器,然后添加一個(gè)模擬器。
第四步:運(yùn)行應(yīng)用:xcrun simctl launch "iPhone 6 (9.0)" com.xxxxx.apollo
后面的com.xxxxx.apollo指的是應(yīng)用的bundle id.
至此,iOS模擬器自動(dòng)構(gòu)建、安裝、運(yùn)行的腳本介紹就結(jié)束了,可能有小伙伴會(huì)抱怨看不明白!我已經(jīng)做好了一整套腳本,只要根據(jù)自己的情況改動(dòng)其中的信息即可,先運(yùn)行device-config新建一套模擬器,有問題請(qǐng)留言,拿走不謝。
鏈接:https://pan.baidu.com/s/1ic-4QQ4AXhmLPiKvn0FKOA 密碼:wh32