Deploying for iOS Simulator

Let's go!

By ahchao in Xcode Learnings

October 31, 2021

Exactly 1 week ago, I had to generate a simulator build for my colleague. In my case, the company doesn’t provide iPhones as test devices (IKR) and we have a situation which prevents us from demoing from our physical device anyway, so we had to improvise.

Simulator build?

A simulator build (as opposed to a normal build for AppStore/Testflight or an Enterprise app) is basically a .app folder that can be used to install on another Mac with simulator.

Reasons for simulator build

A simulator build is useful when we have a Mac but no physical iPhone to demo the project, or for certain scenarios where a demo via the iPhone device is not possible (cable spoil, no wifi, some software issue, etc.), or a QA need to test something quick and the iPhone device is not registered yet. All sorts of possible reasons.

Regardless, we either need have a simulator build available, or the source code to build from. For the latter option, it is not possible if the user (QA/BA/etc) is not supposed to have access to the source code. This left us with simulator builds.

How to run

First, a prerequisite:

Install Xcode.

We need the simulator that comes with it. Simulator is not installed by default on Mac.

Once completed, to run it without running Xcode:

Open Spotlight (cmd + space) and type in “Simulator”, open it up to launch the default simulator.

To install the .app, just drag it over your simulator device home screen.

That’s it!

Things to note

Do note that if you generate a build meant for a M1 Mac, you cannot install run it on an Intel Mac. It will install but will not run:

“XXX” Needs To Be Updated
Failed to find matching arch for input file: /path/to/the/installed/XXX.app/XXX

This just means we cannot run a arm64 binary on the x86_64 simulator (or rather, the Intel chip).

So keep this in mind and always(?) ensure you generate a x86 build. An M1 Mac has no issues running a Intel binary because of Rosetta 2, so no worries about that (you can verify this by looking at Activity Monitor for your app and under Kind it will show Apple or Intel on your M1 Mac).

Intel Mac M1 Mac
x86_64 binary ✅ (via Rosetta 2)
arm64 binary

In our case, we had a third party library that is outdated and it does not contain the binary for a arm64 simulator, so I had no choice but to build for x86. And to keep compatibility for my colleague who might be using Intel of course.

Binary Generation

This is the command I used to generate a x86 build:

xcodebuild ARCHS=‘x86_64’ ONLY_ACTIVE_ARCH=NO -configuration ‘Debug (DEV)’ -scheme ‘my-app (DEV)’ -destination “generic/platform=iOS Simulator” -sdk iphonesimulator ‘SWIFT_ACTIVE_COMPILATION_CONDITIONS=$(inherited) TEST_INTERNAL’

Replace x86_64 with arm64 if you really want to only build/run it for M1 chips.

ONLY_ACTIVE_ARCH must be NO so it will use ARCHS. Otherwise if you are on a M1 MacBook, it will generate arm64 binary.

TEST_INTERNAL is just a env flag I am using, you can omit the whole SWIFT_ACTIVE_COMPILATION_CONDITIONS if not required.

I believe we can remove -destination as well, but I just put it in there to explicitly state a device, otherwise it will just pick a random one that fits the profile we are building for and I don’t want to take any chances.


NOTE

Go Xcode -> Product -> Reveal Build Products Folder to open Finder to the .app (might not be accurate)
Or even better yet, look at the console to determine which path the .app is generated in.


Please do comment if this has helped you in one way or another, or if you have any followup questions!

comments powered by Disqus