Home iOS & Swift Tutorials

Xcode Simulator App Advanced

In this tutorial, you’ll learn about Xcode Simulator’s advanced features to improve your daily development experience.


  • Swift 5, iOS 14, Xcode 12

The Xcode Simulator is one of the tools used most widely by developers. Running and testing apps on the simulator has become part of every developer’s daily routine. Becoming familiar with various simulator options is vital for any developer. Did you know you can create and configure simulators from the command line as well? In this tutorial, you’ll learn:

  • What a simulator is
  • Insights into useful simulator options
  • To create and configure simulators from the command line
  • To stream and capture logs using the command line
  • To create a Bash script to automate launching the app on a simulator in different locales.

Getting Started

Download the project by clicking the Download Materials button at the top or bottom of this page. Open the RayWonders project. Build and run.

Advanced Simulator walkthrough

This app has two tabs — Photo and Map. The Photo tab shows photos of the wonders of the world. Tapping a photo shows a detailed view of its description. The Map tab shows the photos of the wonders of the world as annotations on a map. This is one of the rare raywenderlich.com tutorials where you won’t be modifying the project. Instead, you’ll use this app as a foundation to learn the various simulator options. Before you embark on your world tour, you’ll need to understand what a simulator is.

What Is a Simulator?

The simulator is a great tool to simulate iOS, iPadOS, tvOS, and watchOS on the Mac. It helps rapid prototyping and testing builds by simulating different devices. At a more technical level, a simulator is a separate user space running on the macOS kernel.

Simulator architecture

User space is the system memory allocated to run applications, whereas kernel space is the system memory allocated to run the OS kernel and device drivers. Launching a new simulator creates a separate user space.

The kernel is a core component of the OS. It facilitates interactions between the hardware and software components. It’s responsible for managing the hardware, allocating memory and arbitrating between processes.

One of those processes — Daemon — runs in the background. launchd, cfprefsd, distnoted are some of the system daemons.

Are running an app on a device and on a simulator the same? You’ll learn that next.

Running App on a Device vs. a Simulator

Testing apps on a simulator is very handy. However, there are a few key differences between running apps on a device and on a simulator.

Computing Performance

Simulators share the same computing resources with the Mac. This includes memory, CPU and network connection. In contrast, physical devices have less memory and computing power compared with a Mac. Also, the network can be one unpredictable beast on the physical device.

Device performance vs Mac performance


The resolution and the color gamut on a Mac and the physical device can differ, causing images and text to appear jagged. You’ll learn how to simulate the exact physical device size later in this tutorial.

Hardware Limitations

Some hardware components are not supported in a simulator. These include:

  • Bluetooth
  • Camera
  • Motion sensors such as accelerometer and gyroscope
  • Proximity sensor

Framework Limitations

A few frameworks are not supported in simulator. These include:

  • ARKit
  • HomeKit
  • IOSurface
  • MessageUI

For a more exhaustive list of all the differences, please refer to the documentation by selecting Help ▸ Simulator Help in the Simulator menu.

Next, you’ll learn how to organize the simulators.

Organizing Simulators Using Xcode

Xcode ships with a default set of simulators. To view a list of these simulators, follow these steps:

  1. Open Xcode.
  2. Select the Window menu option.
  3. Choose the Devices and Simulators menu.
  4. Device and simulators in Xcode

  5. Select the Simulators tab.

You’ll see a list of simulators that were shipped with Xcode. If you’ve downloaded other runtimes in the past, you’ll see those associated simulators as well.

Now, you’ll create a new simulator with a custom name.

Create simulator from Xcode

Follow these steps:

  1. Press the + button at the bottom left.
  2. Set the simulator name as Demo.
  3. Select iPhone 12 Pro as the device type.
  4. Select iOS 14.2 as the OS version.
  5. Press Create.

This creates a new simulator with the name Demo, which you can now find in the list of simulators.

Uncheck the Show as runtime destination checkbox for the Demo simulator.

Hide simulator option

This hides the simulator. It won’t show up in the list of simulators next to the app scheme.

Control-click the Demo simulator. Several options appear, such as Delete and Rename.

Delete simulator context menu

Go ahead and delete the Demo simulator by clicking Delete. Don’t worry; you’ll create it using a different method very soon.

Running Older Runtimes

Sometimes you’ll have to run your app on older versions of runtimes.

Download runtimes menu

You can download older runtimes by selecting Download more runtimes in the OS Version drop-down when creating a new simulator.

You can also download more runtimes from the Components window. Select Xcode ▸ Preferences ▸ Components option.

Simulator components window

This window shows the list of the downloaded simulator runtime as well as other runtimes available for download.

Next, you’ll learn an alternative way to create simulators.

Creating Simulators From the Simulator Menu

Build and run.

When the simulator is running, follow these steps:

  1. Select File ▸ New Simulator from the Simulator menu.
  2. Create simulator from menu

  3. Enter Demo as the simulator name.
  4. Select iPhone 12 Pro as the Device Type.
  5. Select iOS 14.2 as the version.
  6. Click Create.

Open the simulator by following these steps:

  1. Select File ▸ Open Simulator from the menu.
  2. Select the iOS 14.2 run time.
  3. Choose the Demo simulator.

Demo simulator

This launches the Demo simulator.

That was fast and easy! Next, you’ll learn about the various size options in the simulator.

Comparing Simulator Size Options

You can resize a simulator by clicking and dragging from one of the four corners. The Window menu options provide four scaling options.

Physical Size

Simulator in physical size mode

Physical size resizes the simulator to match the actual device size. This visualizes how your app looks across different screen sizes.

Point Accurate

Simulator in point accurate mode

Point accurate mode sizes the window so that the content has the same size on devices with different scale factors. As a result, an image on a device with a 3x display appears with the same size as a 2x display.

Pixel Accurate

Simulator in pixel accurate mode

In this mode, the window size changes to the same number of pixels as the physical device. Each pixel on the simulated device maps to one pixel on your Mac’s display. This causes simulators to appear larger on screen if your Mac’s display has a lower pixel density than the simulated device. You can use this mode to check the alignment of images and controls in your app.

Fit Screen

Simulator in fit mode

This resizes the simulator to the size of your Mac display.

Next, you’ll learn the various options provided in a simulator.

Slow Animations

Animations are an integral part of an app experience. Build and run RayWonders in the Demo simulator.

Tap the Photos tab. Next, tap a picture of one of the wonders of the world to present a view of details about the place. Dismiss the view by sliding it down.

To simulate slow animations, select the Debug ▸ Slow Animations option in the Simulator menu.

Slow animation menu option

Tap the picture again. The view now animates slowly.

RayWonders on simulator with slow animation

Viewing the animations slowly can help bring clarity. In addition, it can help in examining problems in rendering and performance.

Next, you’ll learn to simulate Dark Mode. Before proceeding, disable the slow animations by deselecting the Debug ▸ Slow Animations menu option.

Dark Mode

Dark Mode provides a great viewing experience in low-light environments. The simulator provides an option to view your app in Dark Mode.

Toggle appearance menu option

Select Features ▸ Toggle Appearance. This toggles the appearance to Dark Mode. Now, tap the Map tab in RayWonders.

RayWonders map Dark Mode

You’ll notice that the map has changed to a dark appearance. Easy, isn’t it? This is a handy way to test your app in Dark Mode.

To change the appearance back to default, deselect Features ▸ Toggle appearance. To learn how to support Dark Mode, check out Supporting Dark Mode: Adapting You App to Support Dark Mode tutorial.

Next, you’ll learn how to simulate push notifications!

Simulating Push Notifications

Push notifications are a great way to let your users know of new content updates in your app. In the past, testing push notifications was a challenge. You needed a physical device to test the push notifications. Starting with Xcode 11.4, you can simulate push notifications on a simulator.

Create a file named RayWondersPushNotification.apns using the following:

  "Simulator Target Bundle": "com.raywenderlich.RayWonders",
  "aps": {
    "alert": {
      "title": "Hindi language support added!",
      "body": "Checkout RayWonders in Hindi!"

This is a simple, visible push notification payload with a title and a body. The Simulator Target Bundle is a special key. It specifies the bundle ID of the app that should receive the notification.

Before trying the payload, you need to first grant the notification permission in the app.

Grant notification permission

Follow these steps:

  1. Open RayWonders in the Demo simulator.
  2. Tap the bell icon on the top right in the Photos tab.
  3. Select Allow in the notification permission prompt.
  4. Select Device ▸ Home from the Simulator menu to put the app in the background.
  5. Home menu option in simulator

Next, drag and drop RayWondersPushNotification.apns file on the Demo simulator.

Simulate push notification using drag and drop

Ta-da! A visible push notification appears. That was easy! Bear in mind that a simulator can only simulate a push notification. To test an actual push notification received from the Apple push notification server requires a physical device.

To learn about push notifications in more depth, read this Push Notifications Tutorial: Getting Started.

Next, you’ll learn how to zoom.

Zooming In and Out

Open RayWonders in the simulator. Switch to the Map tab. The map is centered and zoomed in on a wonder of the world. Where are the other wonders of the world?

You’ll need to zoom out to see the world view. Click and drag while holding down the Option key.

Zoom and pan in simulator

Clicking and dragging is great, but it can soon get tiresome. Next, you’ll learn a quicker way to go to a location.

Simulating a Location

The simulator provides an easy way to simulate a location. First, you need to grant location permissions in RayWonders.

Grant location permissions

Follow these steps:

  1. Open RayWonders in the simulator and switch to the Map tab.
  2. Tap the Start Location Services button in the Map tab.
  3. Select the Allow While Using App permission.

Now, to simulate location:

  1. Select Features ▸ Location ▸ Custom Location from the Simulator menu.
  2. Simulate location menu

  3. Enter 41.8902142 as the latitude and 12.4900422 as the longitude.
  4. Click OK.
  5. Simulate location coordinates

This takes you directly to the Colosseum on the map — your fastest journey ever!

Colosseum on the map

However, entering the coordinates for each location to simulate is quite a memory-intensive — your memory, that is — task. Next, you’ll learn an easier solution to this problem.

Sharing Locations From the Maps App

The Maps app on macOS provides an easy way to share locations with your simulator.

Simulate location from Maps app

Follow these steps:

  1. Open the Maps app.
  2. Enter Machu Picchu in the search text.
  3. Click the Share button next to the search field.
  4. Choose Simulator from the drop-down.
  5. In the location prompt, select Demo as the simulator.
  6. Simulator menu option in Maps

  7. Click Send.

You’re now in Machu Picchu in the simulator’s map view.

Location simulated in RayWonders

Congratulations! You’ve just created a world record as the fastest traveler from the Colosseum to Machu Picchu! :]

To learn about handling location in your app in more depth, check out MapKit and Core Location.

Now, it’s time to shake things up.

Simulating Shake Gesture

Shake gestures are great cues to prompt the user to give feedback in an app. But how can you shake a simulator? Thankfully, shaking the Mac rigorously is not the solution. The simulator provides an easy way.

Open RayWonders on the Demo simulator. Select Device ▸ Shake from the Simulator menu.

Shake menu option

This simulates a shake gesture.

Shake detected in RayWonders

RayWonders detects the shake and prompts an alert to the user. You can detect and handle shake gestures in your app by implementing the method motionEnded(_:with:). To learn more, check out the Apple documentation.

Next, you’ll learn how to simulate a memory warning.

Simulating a Memory Warning

iOS sends a warning to the app when its memory usage approaches the upper limit on the device. The app needs to respond by purging the cache data, which can be re-created later.

Open RayWonders on the Demo simulator. Select Debug ▸ Simulate Memory Warning from the menu.

Memory warning menu option

This simulates a memory warning.

Memory warning in RayWonders

RayWonders shows an alert. You can learn more about handling memory warnings in this Responding to Memory Warnings Apple documentation.

So far, you’ve seen some useful simulator options. There are several others that aren’t covered in this tutorial. You should check them out, depending on your app needs. Some of these options include:

  • Simulate iCloud sync using Features ▸ Trigger iCloud Sync.
  • Simulate Apple Pay authorization using Features ▸ Authorize Apple Pay.
  • Trigger Siri using Device ▸ Siri.
  • Check System Log using Debug ▸ Open System Log.

Next, you’ll learn to interact with simulators using the command line.

Organizing Simulators Using the Command Line

So far, you’ve created and managed simulators using Xcode. In addition, you’ve also learned the various Simulator menu options. Now, you’ll learn to manage and use simulators from the command line.

Open Terminal. Enter the following command:

xcrun simctl --help

and press Enter.

The help option provides the list of all the subcommands available using simctl.

Simctl Help command

Simctl is a tool to help manage and programmatically interface with the simulator. You can access simctl using the xcrun command-line tool.

Now, you’ll explore several of these subcommands. Run the following:

xcrun simctl list

The list command shows the list of all the available devices and the runtimes.

Simctl List command

It also shows the current state of the devices, whether it’s Booted or Shutdown.

Next, you’ll learn to create and launch a simulator from the command line.

Creating Simulator From the Command Line

Before creating a new simulator, delete the Demo simulator created via Xcode. Enter the following:

xcrun simctl delete Demo

The delete command identifies a simulator and deletes it. Now, create a new simulator from the command line.

Enter the following:

xcrun simctl create Demo "iPhone 12 Pro" "iOS14.2"

The create command takes in a device type and runtime and creates a simulator. This creates an iPhone 12 Pro simulator with iOS 14.2 runtime.

Now, Terminal shows the unique identifier of the new device.

Simctl Create command

Enter the following:

xcrun simctl boot Demo

The starts the Demo simulator. By default, it’s in the Shutdown state.

Now, install RayWonders using the command line. You’ll first need the app bundle. Follow these steps:

  1. Open the Project navigator and select RayWonders.app, located in the Products folder.
  2. RayWonders in Project navigator

  3. Right-click and select Show in Finder.
  4. RayWonders in Finder window

  5. Copy RayWonders to your home directory.

Open Terminal and navigate to the home directory by entering the following:

cd ~

Next, run the following:

xcrun simctl install Demo RayWonders.app

The install command installs RayWonders on the simulator. Great job!

You can even launch the app using simctl. Enter the following:

xcrun simctl launch Demo com.raywenderlich.RayWonders

The launch command takes the app bundle ID as a parameter. RayWonders launches in the Demo simulator.

Congratulations! You’ve now created, booted, installed and launched a simulator from the command line. Here are some other options you can try:

  • terminate: This terminates an application using the bundle identifier.
  • erase: This erases the device contents.
  • uninstall: This uninstalls the application. You’ll need to specify the bundle identifier of the application.

Next, you’ll learn some cool commands that are available for your app.

Taking Screenshots

Screenshots of your app can be useful in several scenarios. For instance, you’ll need screenshots when submitting your app in AppStore.

Enter the following command:

xcrun simctl io Demo screenshot screenshot.png --type="png"

This takes a screenshot of the current screen and saves it to the file screenshot.png. In addition to a png, screenshot command supports other file formats, such as TIFF, BMP, GIF and JPEG.

A screenshot can show what your app looks like, and a picture is worth a thousand words. However, a video is worth a lot more. :]

Recording Video

You can record videos of your app using simctl. To start recording, enter the following command:

xcrun simctl io Demo recordVideo Demo.mov --codec="h264"

Interact with RayWonders on the simulator. Press Control-C in the terminal when you have finished. This saves the video in Demo.mov.

In addition, you can specify the desired codec when recording. The default codec is hevc.

Record video using command line

The recordVideo command helps avoid using a QuickTime player to record a video of your app.

Customizing the Status Bar

Check the app’s status bar in the simulator. You can see that the battery is full, the device has the best signal and the time on the simulator is your local Mac time. What do you do if you want to override these?

Enter the following command in Terminal:

xcrun simctl status_bar Demo override \
  --dataNetwork 4g --cellularBars 2 --batteryState charging \
  --batteryLevel 25 --time 12:05

This overrides the status bar to set:

  • Data network as 4G
  • Cellular signal to two bars
  • Battery state to charging and the battery level to 25%
  • Time on the simulator to 12:05

Status bar in RayWonders

When you do this in your own project, you can set the status bar information to whatever you want.

The status_bar command can be really handy when you want to customize the appearance of your app screenshots and videos.

When you are done, revert the status bar to the default appearance by entering the following:

xcrun simctl status_bar Demo clear

Debugging and Diagnosing

Simctl also provides several commands to help debug and diagnose issues.

Go back to Terminal, and enter the following:

xcrun simctl get_app_container Demo com.raywenderlich.RayWonders

get_app_container prints the app bundle’s path.

Get app container using Simctl

You can inspect the data within the app container using this path. In addition, your simulator logs can be really useful when debugging issues.

Now, type the following in Terminal:

xcrun simctl spawn Demo log stream

This starts streaming all the logs from the Demo simulator.

Stream simulator logs

However, this can be too much data to inspect. Press Control-C to stop the stream.

Try the following:

xcrun simctl spawn Demo log stream | grep com.raywenderlich.RayWonders

This filters the logs and displays only those from RayWonders.

Stream RayWonders logs

As you interact with the app, you’ll see more logs displayed in the terminal. These logs can be extremely useful when filing a bug or providing feedback to Apple.

Type the following:

xcrun simctl diagnose

The diagnose command collects a bunch of data, including logs and crashes. It also generates files that can help Apple debug issues. By default, the collected logs are for the booted device. By specifying the UDID of a device, you can constrain the collection of logs to that particular device.

You’ve now become a simulator command line expert! You can take it a step further by automating common actions using Bash scripts.

Automating Using a Bash Script

Now, you’ll create a script to clone a simulator and launch RayWonders in a different locale.

First, open Terminal, and enter the following:

touch sim_utility.sh

This creates a new file with the name sim_utility. The .sh extension denotes that it’s a shell script.

Note: You can create the script anywhere in your file system. For organization purposes in the sample project, the script is located under `Scripts` folder.

Next, run:

chmod +x sim_utility.sh

This makes the sim_utility.sh executable so you can run it.

Open sim_utility.sh in an editor, and add the following:



get_id_of_simulator() {

get_status_of_simulator() {

launch() {

case $COMMAND in
"launch") launch "$3" "$4" "$5" ;;
  exit 1

Here’s what’s going on:

  1. The script takes in a command name and a simulator name as the command line parameters.
  2. get_id_of_simulator, get_status_of_simulator and launch are empty stubs that you’ll implement next.
  3. The script currently supports one command named launch. The launch takes three additional parameters, which you’ll implement soon.

In get_id_of_simulator, replace #TODO with the following:

xcrun simctl list | grep "$SIMULATOR_NAME" | \
awk 'match($0, /\(([-0-9A-F]+)\)/) {print substr( $0, RSTART + 1, RLENGTH-2 )}'

get_id_of_simulator searches the list of a simulators to match the name specified as a parameter. If it finds a match, the substring operation gets the unique identifier of the simulator.

In the get_status_of_simulator method, replace #TODO with the following:

xcrun simctl list | grep "$SIMULATOR_NAME" | \
awk 'match($0, /\(([a-zA-Z]+)\)/) {print substr( $0, RSTART + 1, RLENGTH - 2 )}'

get_status_of_simulator searches for a simulator with a matching name in the list of devices. If it finds a match, it gets the status of the simulator — booted or shutdown. You’ll use these in the launch.

Implementing Launch

In launch, replace #TODO with the following:


if [ -z "$SIMULATOR_ID" ]; then
  echo "No device matching the name: $SIMULATOR_NAME"

echo "Simulator id: $SIMULATOR_ID"
echo "Bundle id: $BUNDLE_ID"
echo "Locale: $LOCALE"

echo "Simulator Status: $SIMULATOR_STATUS"
if [ "$SIMULATOR_STATUS" = "Booted" ]; then
  echo "Making sure the device is shutdown first..."
  xcrun simctl shutdown "$SIMULATOR_NAME"

echo "Cloning the device with name $LOCALE..."
xcrun simctl clone "$SIMULATOR_NAME" "$CLONE_NAME"

echo "Booting device..."
xcrun simctl boot "$SIMULATOR_NAME"
xcrun simctl boot "$CLONE_NAME"

echo "Launching app..."
xcrun simctl launch "$SIMULATOR_NAME" "$BUNDLE_ID"

xcrun simctl launch "$CLONE_NAME" "$BUNDLE_ID" -AppleLocale "$LOCALE" \
  -AppleLanguages "($LANGUAGE)"

Save the file. Here’s what this does, step by step. It:

  1. Gives additional parameters to launch, including the bundle ID of the application, the locale and the language to launch your app in. It declares a local variable CLONE_NAME, which is the name of the cloned device. In this case, the name of the cloned device is the locale you specify;
  2. Fetches the simulator’s ID by calling get_id_of_simulator. Then, it stores the result in SIMULATOR_ID. If there is no matching simulator, it exits the program;
  3. Fetches the simulator’s status by calling get_status_of_simulator. If the status is Booted, it runs the shutdown command to shut it down. To be cloned, a device must be shut down;
  4. Clones the simulator using the clone command;
  5. Boots both the original simulator and the cloned simulator using the boot command;
  6. Launches the app on the original simulator using the launch command;
  7. Launches the app using the launch command on the cloned simulator. It specifies the locale and language for the app to launch in.

Launching RayWonders in a Different Locale

Open Terminal, and run the following:

./sim_utility.sh launch Demo com.raywenderlich.RayWonders hi_IN hi

RayWonders launches in Hindi on a cloned simulator with the name hi_IN.

RayWonders in Hindi

No more going to the settings and switching the device language to test your app. You can now see your app in multiple languages simultaneously. Great job!

Note: If you’ve encountered issues running the script, make sure you have just one simulator with the name Demo. You can check the number of simulators available by running xcrun simctl list | grep Demo in the terminal. Delete any duplicate simulators and try again.

RayWonders also supports a few other languages. Run the following:

./sim_utility.sh launch Demo com.raywenderlich.RayWonders ja_Jp ja

RayWonders now launches in Japanese on a new simulator.

RayWonders in Japanese

As a fun challenge, implement two more commands in the sim_utility script.

  • Cleanup: This deletes a simulator given a simulator name.
  • Help: This prints a menu of all the commands supported by the script.

You’ll find the final version of the script with all these options implemented in the Scripts folder in the downloaded materials.

Where to Go From Here?

Download the project by clicking the Download Materials button at the top or bottom of this page.

In this tutorial, you’ve learned tons of useful simulator and command-line options. To learn more, please check out these WWDC videos:

I hope you’ve enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below.




More like this