When developing a mobile app, you need to build and run your app on a simulator or device to test it and view the changes. This is unlike working with web apps where you don’t need to build the app every time.
When working with React Native and iOS, it’s typical to use Xcode as build tool. Building apps that run on iOS requires at least some Xcode knowledge.
In this tutorial, we’ll walk you through some best practices to help you get started using Xcode and offer some tips that will change the way you develop iOS apps with React Native.
Here’s what we’ll cover:
- What is Xcode?
- Building a React Native app on iOS with Xcode
- Running a React Native app on a real iOS device
- Using a simulator to run and test your code
- Xcode schemes
- Working with the
What is Xcode?
Xcode is an IDE and code editor created by Apple to help developers build Apple products — namely, mobile apps for iOS and desktop apps for macOS.
Xcode is a complete environment that contains a set of integrated tools and apps designed to assist with all development processes, including testing, building, deploying, compiling, and debugging.
Building a React Native app on iOS with Xcode
You can build a React Native app either on a simulator or on a real device. If you intend to run it on an iOS device or simulator, the use of Xcode is often required.
You can build a React Native app either using the React Native CLI, which allows you to run build commands from your terminal, or Xcode. I prefer to use Xcode for the following reasons:
- Xcode shows more details about the build process in real time, such as logs
- Xcode enables you to make customizable build configurations. When using Xcode directly, you can adjust build process to your liking. For example, you can choose the type of simulator or device, build with a custom scheme, etc.
- React Native CLI runs some Xcode features using scripting code under the hood. The CLI offers the simplicity to run and build the code with just one command line
- When using only the CLI, you may run into unexpected issues with the build. Using Xcode directly gives you clear picture and helps you identify the cause of a given issue
Let’s walk through how to build and run a React Native app with the React Native CLI. Then, we’ll do the same directly on a real device.
Using the React Native CLI
The React Native CLI is a simple and straightforward way to get your React Native app running. When you first install a React Native app using the CLI, it provides simple instructions and allows you to start, build, and run the app in one simple command:
You can also use npx:
npx react-native run-ios
Basically, this runs bunch of scripts in the background that interact and instruct Xcode to run and lunch the simulator. If you don’t specify a simulator, the CLI uses the default one it finds on Xcode. Here’s how to tell the CLI which simulator you want to run the app on:
react-native run-ios --simulator "iPhone X"
If you want to run your app on a device, you must first make sure your device is connected via USB to your computer. Then, run the CLI command with
react-native run-ios --device "Said's iPhone"
Using Xcode directly
The second way to build and run a React Native app is to use Xcode directly, which is the method I use.
Inside Xcode navigate to
File → Open and browse to your project directory. In the
iOS folder, select
appName.xcodeworkspace if you have one.
You can build the app by going to the tab navigator (
Product→ Build) or using the shortcut
⌘ + B:
It’s a good practice to use the simulator to run and test the app. However, sometimes it’s necessary to test the accuracy of the UI on a real device.
Running a React Native app on a real iOS device
The most obvious benefit to running you app on the device is that it enables you to experience your app the way the user sees it. Simulators are limited and don’t always represent the app with total accuracy. For example, you can’t access the device camera when using a simulator.
I prefer always to use the device because it gives me a more complete idea of how the app works on the user’s end.
To run and build a React Native on a real device, you must have:
- An iOS device; the macOS only allows you to run iOS apps on iOS devices (iPhone, iPad, Apple TV, etc.)
- A USB connector to connect the device to your Mac computer
- An Apple developer account
After connecting the iPhone, the Xcode will show the connected devices as a target:
In my case, the name of my iPhone is “iPhone.” You may see a different name for your device, such as “Tony’s iPhone.”
Select the device you want to build and run the app on, then click the build button. The React Native CLI will automatically open a terminal and start the server. If it’s not started yet, you can go to your terminal and run
If your build is successful, the app will launch automatically on your device:
To ensure that the device is connected to the server, you can go to the terminal and press
r to reload the app or
d to open the developer menu. Alternatively, you can shake your device to pull up the developer menu.
You should see the live reload working as well:
As you move forward in your React Native development journey, you’ll find yourself dealing with unexpected issues, especially with the app build. These issues usually stem from either mismatched versions between React Native packages and iOS or the tools used to build the app, such as Xcode.
Over time, you’ll become familiar with these issues and more efficient in solving them.
Using a simulator to run and test your code
The simulator is a just a virtual device, but it has almost everything you need to test and run your code. Let’s explore some things you can do with a simulator.
The simulator provides a variety of features for debugging your app, especially the accessibility features. For example, you can enable
Color blended Layers to test colors’ accessibility.
In the Xcode, Open the Debug tab:
Testing dark mode
If you have the latest version of Xcode (12.4), there is a feature that enables you to see what your app looks like in dark mode. You can preview your dark mode by hitting Shift + Command + A or by navigating to the Features tab and clicking Toggle Appearance:
GPS location simulator
You can simulate GPS location using the simulator. By default, the simulator has one GPS point, but you can add custom GPS locations:
If you’re using Xcode 10 or below, navigate to Debug → Location → Custom Location. Enter the longitude and latitude and the simulator will use these custom coordinates as the default location for the device.
An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.
You can use schemes to create different builds for your app. This enables you to test the app in different environments. For example, you could create a build just for the test, staging, development, and production builds.
Let’s say we have to create three different builds: a build for testing or staging, a development build, and a build for production. Each build will have a unique build identifier and a custom name.
To see how this works, let’s create the schemes: staging, production, development.
Go to Product → Manage Scheme:
Click the + to create a new scheme:
Do the same with
Staging. Make sure to uncheck the default scheme:
Check all the three builds you just created:
The next step is to set specific build settings for each scheme. Go to Product → Scheme → Edit Scheme:
You can select the type of build configuration you want to use when the app is running, among many other options:
Working with the
info.plist is an XML file that’s used to store a list of app properties, such as the
AppName, version, permissions description, settings, etc.
When an Xcode project is created it comes with a
info.plist by default. You can have multiple
plist files in one workspace. You might create more than one
plist file for different environments — for example,
Development.plist. Only one file can be used at a time.
Given that we created a file for staging (
Staging.plist), right-click on the project directory and select
Property Lis file and give it a name, such as
It’s best to copy the values from the
info.plist, then make a change to it to avoid any syntax issues. Open the file as source code, then copy and paste.
Let’s change the app
displayName in the
Now we need Xcode to use
Staging.plist instead of
info.plist when building.
First, we need to create a build configuration and associate the staging file with it. Click on the project icon, then look for Configurations in the Info tab. Simply duplicate a Debug or Release config, create a new configuration, and name it
After creating the staging build configuration, the next step is to tell the Xcode what property list file it should use when a specific build is used. In our case, we want it to use
Staging, so we have to add the path of
Go to the build settings, look for the Packaging tab, and click on the
info.plist file. It will extend and the three build configurations we have —
Release , and
Staging — will display. Add the path to
Staging, which is
Now, when running the Staging Build configuration, it will use
You can use
info.plist to add and declare permissions of the iOS feature your app has access to. If your app is trying to use APIs that requires permission, you need to add the description of the usage into the
info.plist. For example, if your app is using the native camera feature, you need to add the usage description, as shown below.
Click the + button and look for the
Privacy- Camera Usage Description:
Then, add the value description of the usage on the right:
Knowing how to use Xcode when building iOS apps with React Native is a game-changer. With a solid foundation in Xcode, you can more easily identify and fix build issues more efficiently. Most importantly, knowing how to get the most out of Xcode’s features will improve the developer experience overall and help you do more with your iOS applications in React Native than you previously thought possible.
LogRocket: Full visibility into your web apps
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.