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!