iOS Simulator & xcrun simctl - Part 1

30 Mar 2016

For a continuous integration system it’s essential to orchestrate the test system with command line tools. Since Xcode 6 the iOS Simulator can be controlled via xcrun simctl. To get a reproducible build on a CI system like Jenkins, it’s a good practice to reset the iOS Simulator before each test run.

xcrun simctl create & delete

$ xcrun simctl create
Usage: simctl create <name> <device type id> <runtime id>

$ xcrun simctl delete
Usage: simctl delete <device> [... <device n>] | unavailable

This looks fairly simple. Let’s create a new iPhone 5 device with the iOS 9.3 runtime:

$ xcrun simctl create 'iPhone 5' \
    com.apple.CoreSimulator.SimDeviceType.iPhone-5 \
    com.apple.CoreSimulator.SimRuntime.iOS-9-3
021A13B3-FA17-4DDA-8CB8-717D3BAC4CB6

Delete it again:

$ xcrun simctl delete 021A13B3-FA17-4DDA-8CB8-717D3BAC4CB6

Where did these magic strings com.apple.CoreSimulator.SimDeviceType.iPhone-5 and com.apple.CoreSimulator.SimRuntime.iOS-9-3 come from? The list of available device types and runtimes can be retrieved like this:

$ xcrun simctl list devicetypes
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
...

$ xcrun simctl list runtimes
== Runtimes ==
iOS 8.4 (8.4 - 12H141) (com.apple.CoreSimulator.SimRuntime.iOS-8-4)
iOS 9.3 (9.3 - 13E230) (com.apple.CoreSimulator.SimRuntime.iOS-9-3)
...

And so can the devices:

$ xcrun simctl list devices
== Devices ==
-- iOS 8.4 --
    iPhone 5 (F04B61AE-3B34-4200-A907-1B95EE1BA463) (Shutdown)
-- iOS 9.0 --
    iPhone 5 (4132E910-D471-4978-868E-A020E359F661) (Shutdown)
...

This is good enough for simple tasks and can be easily used in any scripting language. Luckily these list commands support in the most recent versions of Xcode a JSON formatted output. This comes in very handy and makes an abstraction in any programming language easy.

simctl gem create & delete

I have created such an abstraction in form of a Ruby Gem called simctl. It is available via RubyGems and can be installed via Bundler:

gem 'simctl'

Once installed, the usage is simple. Using the same example of creating and deleting an iPhone 5 device with iOS 9.3 runtime:

require 'simctl'

runtime = SimCtl.runtime(name: 'iOS 9.3')
devicetype = SimCtl.devicetype(name: 'iPhone 5')
device = SimCtl.create_device('iPhone 5', devicetype, runtime)

After that you can interact with the device object. See a list of available methods here.

Deleting the device is as simple as device.delete!. But what if you need to find the same device again in another script? All devices have a unique identifier. simctl supports finding devices by this so called udid, but it also can find them by various other properties.

device = SimCtl.device(udid: '63B9D9E5-CD93-484E-9D48-BD2C24BC1B73')
device.delete!

That’s all so far, I’m planning to write another post about more advanced usages of the simctl gem.

Follow up on part 2.