While developing iOS apps, simulators are the best friends of developers. It’s the quick and easy way to test app while development as we can interact with iOS simulators using GUI. Apple’s documentation on getting started in the simulator is awesome and we can learn almost everything about controlling simulators from using graphical user interface.
Although simulators are easy to use with GUI, it’s a bit painful to script simulator interactions to run on Continuous Integration server. Fortunately, Apple has nice command line utility called “simctl”.
In this post, let’s see how to use ‘simctl’ to interact with iOS simulators. We will cover following
- Creating, Deleting and Booting Simulators
- Adding photos and video to simulators
- Installing/Uninstalling, launching/Terminating app inside simulator
- Capturing screenshot and record video of simulator
- Collecting the simulator logs and other tricks
simctl
Apple has ‘simctl’ binary to interact with iOS simulators from the command line. It’s very similar to the adb for Android. Again it’s another utility poorly documented by Apple but we can find binary at /Applications/Xcode.app/Contents/Developer/usr/bin/simctl and we can use it with xcrun utility. We can access all the available options using the help command
1 |
$ xcrun simctl help |
We can perform various actions on iOS simulator using ‘simctl’ from creating new simulator, erasing simulator, installing app inside the simulator, add photo/video to the simulator and may more. Let’s look into few of them in details.
Listing all available simulators
We can easily list all the available simulators using command
$ xcrun simctl list
This command will list all the available simulators with the runtime. It will also show ‘booted’ simulator if it’s running already.
CRUD operations on Simulators
We can create, erase, delete, boot, shutdown and upgrade simulators using simctl.
Create
We can easily create new simulator called ‘My-iPhone7″ on top of existing iPhone7 (iOS 10.3) simulator using command
1 |
$ xcrun simctl create My-iphone7 com.apple.CoreSimulator.SimDeviceType.iPhone-7 com.apple.CoreSimulator.SimRuntime.iOS-10-3 |
We can see that newly created simulator using list option and we have UUID for the simulator ‘C86A559A-1F50-40D1-8D84-954EDFBBCE18′
Shutdown/Erase/Boot
As we have already seen that, there is another simulator already booted, let’s shut it down and erase its content. The order is important here, we can’t erase simulator in the booted state, we need to shut down first then erase.
1 2 |
$ xcrun simctl shutdown C8C050F3-062D-4444-A888-BBEC783E31BD $ xcrun simctl erase C8C050F3-062D-4444-A888-BBEC783E31BD |
Boot
Now let’s boot the newly created simulator using new UUID
1 |
$ xcrun simctl boot C86A559A-1F50-40D1-8D84-954EDFBBCE18 |
Now that, we have learned how to shutdown, boot and erase simulator. Let open any simulator by using
1 |
$ open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/ |
You can see that simulator is booting.
Add Photo/Video to Simulator
An iOS simulator by default has 5 images but we can add more images or video using simctl addmedia functionality. Let’s add one photo(png) and on video(gif) inside our simulator which is kept on the desktop.
1 |
$ xcrun simctl addmedia booted ~/Desktop/shashi.png |
Now, the simulator will have another photo. Similarly, we can add video as well.
1 |
$ xcrun simctl addmedia booted ~/Desktop/simctl_list.gif |
Install/Uninstall app inside Simulator
We can easily install our app inside simulator from the command line if we already have a path to .app file from derived data. Let’s create new single view app in Xcode and name it “CLI” and save it on the desktop. We need to build the app using xcodebuild to get CLI.app in the derived data.
1 |
$ xcodebuild build build -scheme "CLI" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO |
Now, we will get the CLI.app inside derived data, in my case it’s inside /Users/shashi/Library/Developer/Xcode/DerivedData/CLI-dxasphjukowuptcqxzbmyaqgpbqp/Build/Products/Debug-iphoneos/CLI.app directory.
We can install our CLI.app inside simulator using
1 |
$ xcrun simctl install booted /Users/shashi/Library/Developer/Xcode/DerivedData/CLI-dxasphjukowuptcqxzbmyaqgpbqp/Build/Products/Debug-iphoneos/CLI.app |
Watch the GIF below where we are installing CLI.app
Similarly, we can uninstall our iOS app from simulator easily. We need to know the bundle identifier of our app. In my case it’s test.CLI we can uninstall app using
1 |
$ xcrun simctl uninstall booted test.CLI |
Launch/Terminator app inside Simulator
Similar to installation, we can launch and terminate an app using command line using simctl. We have to make sure app is installed before we launch.
1 |
$ xcrun simctl launch booted test.CLI |
We can see that app is launched, we can then terminate app using
1 |
$ xcrun simctl terminate booted test.CLI |
Screenshot and Video Recording of Simulator
In Xcode 8.2, Apple introduced this really nice feature of capturing the screenshot and recording video of the simulator. Now it’s easy to capture a screenshot of the simulator. We can capture current state of simulator using
1 |
$ xcrun simctl io booted screenshot screen.png |
This will save the screenshot of the simulator in the current working directory with file screen.png
Similarly, we can record video of simulator while using app and save it on disk using
1 |
$ xcrun simctl io booted recordVideo news.mov |
This will save video of the simulator to news.mov file which can be played using Quick Time player or similar.
Collecting Simulator Logs
Sometimes it would be helpful to print the simulator logs as console output. We can easily determine the activity of the simulator by reading the logs. Let’s print the logs of simulators
$ xcrun simctl spawn booted log stream --level=debug
we can also filter the log output if you looking for logs of the particular app
1 2 3 4 5 6 7 8 9 |
# filter log output xcrun simctl spawn booted log stream --predicate 'processImagePath endswith "CLI"' xcrun simctl spawn booted log stream --predicate 'eventMessage contains "error" and messageType == info' # collect log data xcrun simctl spawn booted log collect # open location i cd `xcrun simctl getenv booted SIMULATOR_SHARED_RESOURCES_DIRECTORY` |
Miscellaneous Bulk Actions
There are a couple of dirty hacks which might be useful as well in some cases when you don’t want so many simulators.
Erase all Simulators
We can erase all the simulators using the simple command
1 |
$ xcrun simctl erase all |
Delete all the Simulators
The following script will delete all your simulators so beware of the impact and use when really needed.
1 |
$ xcrun simctl list | awk -F "[()]" '{ for (i=2; i<NF; i+=2) print $i }' | grep '^[-A-Z0-9]*$' | xargs -I uuid xcrun simctl delete uuid |
Find Simulator by Name Regex
Sometimes we might need to find the simulator by name and perform an action on that UUID. We can find that UUID using the name and then erase/delete/boot simulator. Let’s erase simulator containing name “Shashi”
1 |
$ xcrun simctl list | grep -w "Shashi" | awk -F "[()]" '{ for (i=2; i<NF; i+=2) print $i }' | grep '^[-A-Z0-9]*$' | xargs -I uuid xcrun simctl erase uuid |
Conclusion
Using simctl utility we can programmatically interact with iOS simulators and script the setup for test execution on CI servers. What’s your experience with ‘simctl’, comment below