目前大多数iOS应用需要兼容到iOS8.0,那么问题来了,在测试设备不够的情况下,我们只能使用模拟器来凑数进行兼容性测试。但是iOS开发运行流程对于开发者来说是正常操作,但是对于测试人员来说可能就有点难受了,尤其是某些情况下我们需要执行pod install等前置操作。那么假设我们的测试人员不关心我们的代码,也不关心应用在运行前需要做哪些准备工作,我们该如何做到一键模拟器运行app呢?本文以iPhone应用为例来实现模拟器自动构建、自动安装、自动启动的shell脚本,本文假设有个名称和target都是“Apollo”的项目。
1.xcode运行应用
我们知道利用xcode利用模拟器运行应用就是Run按钮一键或者是Command+R的事,但其实在底层这些操作都是触发一系列shell脚本来构建安装启动模拟器和应用。xcode安装的同时提供了xcodebuild/xrun/instruments等工具,给我们的模拟器应用自动构建提供思路。
2.思路1
异于真机,模拟器安装的应用包并非是.ipa文件,而是.app文件,将.ipa文件解压后得到文件夹Payload,里面正好有个.app文件。那么这个是否就是我们所需要的呢,我们尝试启动一个模拟器,然后将.app拖到模拟器屏幕内,发现安装成功了,但是启动之后立即闪退。
其实闪退并非是因为.ipa内的.app不能在模拟器运行,而是ipa都是针对真机打出来的,如果项目中含有模拟器不能运行的内容自然就会闪退。
这里插一嘴,大部分静态库,如果不支持模拟器运行,我们都可以使用“#if TARGET_IPHONE_SIMULATOR”进行屏蔽,那么在链接时就不会链接到包中,运行时就不会闪退。
3.思路2
根据上面的经验,并不是所有的.ipa中的.app都能在模拟器中运行,为了保险起见中这种方式并不可用。
每次我们xocde编译时,都会生成一个.app文件:
这个文件的位置在/Users/xxxx/Library/Developer/Xcode/DerivedData/xxxxxxx/Build/Products/Debug-iphonesimulator/xxxxx.app,我们可以右键Show in Finder查看。
我们将这个.app拖到模拟器中安装后发现启动还是闪退,原因是xcode编译时选中的设备是Generic iOS Device,这也是真机。将设备切到模拟器后编译重试,发现完美运行,那么这个.app就是我们想要的。
4.编译脚本
根据以上的尝试,我们基本确定了思路,就是需要以模拟器为设备编译项目得到.app,并安装到模拟器后启动。
第一步:使用编译项目命令:
xcodebuild -workspace Apollo.xcworkspace -scheme Apollo -sdk iphonesimulator11.4 -configuration Debug
如果项目没有集成cocoapods,请用-project。
这里插一嘴,可以使用man xcodebuild来查看文档:
-sdk iphonesimulator11.4意思就是以模拟器为设备编译项目。那么这里如果不知道你的模拟器sdk版本,可以使用xcodebuild -showsdks查看支持的sdk:
第二步:启动一个模拟器:
crun instruments -w "iPhone 6 (9.0)" 或者 instruments -w "iPhone 6 (9.0)"
这里-w后面可以跟模拟器的名字,也可以是模拟器的id。
补充一句,兼容测试,前提是你机器上已经下载了8.x,9.x,10.x,11.x版本的模拟器了:
如果你想查看本机instruments支持的模拟器名字、id等信息,请使用:instruments -w device
其中前面是名字,后面[]中间的是id(id不包括[])。
本人推荐使用名字不使用id,因为不同电脑的模拟器的id是不一样的,甚至同一台电脑登录的不同两个用户看到的设备id也是不一样的,但是名字可以是自定义的唯一的。而且,我也不推荐使用xcode自己生成的模拟器的名称,为什么后面会讲到。
第三步:将编译生成的.app文件安装到模拟器:
xcrun simctl install "iPhone 6 (9.0)" ~/Library/Developer/Xcode/DerivedData/Apollo-bepdsvfodytknjgsadpphjerbphz/Build/Products/Debug-iphonesimulator/Apollo.app
那么问题来了,这里的路径是唯一的吗?答案当然不是,这里项目后面的长字符创是xcode随机生成的,目前我没有找到更好的办法,我尝试过改变xcode默认的编译生成文件的位置,但是它仍然会生成这样一个随机文件夹名。但是有点好的是,同一个项目,只要编译过一次,那么这个文件夹名就固定了,甚至你去删除这个文件夹,xcode在下一次编译时还会生成同样名称的文件夹,所以可以这么说,在同一电脑上,同一项目的编译目录是确定的。
这里的"iPhone 6 (9.0)"可以是模拟器名称和模拟器id,或者直接使用booted安装到启动的模拟器,但是我们可能同时启动多个模拟器,这种情况就不可控了,可以使用xcrun simctl list devices查看xcrun simctl支持的模拟器信息:
可以看到,xcrun simctl与instruments列出来的模拟器是有所不同的,xcrun simctl并不是以"iPhone (版本号)"形式命名的。为了双方统一名称,我使用了xcrun simctl delete和xcrun simctl create来重新创建一套模拟器来使用:
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";
先尝试删除该名称模拟器,然后添加一个模拟器。
第四步:运行应用:xcrun simctl launch "iPhone 6 (9.0)" com.xxxxx.apollo
后面的com.xxxxx.apollo指的是应用的bundle id.
至此,iOS模拟器自动构建、安装、运行的脚本介绍就结束了,可能有小伙伴会抱怨看不明白!我已经做好了一整套脚本,只要根据自己的情况改动其中的信息即可,先运行device-config新建一套模拟器,有问题请留言,拿走不谢。
链接:https://pan.baidu.com/s/1ic-4QQ4AXhmLPiKvn0FKOA 密码:wh32