Skip to content

Exporting to iOS

Getting your game onto an iPhone or iPad.

Rough edges in 0.1.0

The iOS path builds, signs, installs and launches on a real device — but not every part of it is equally exercised. Building and running on a connected device is the best-tested route. The Archive .ipa action and the generated Xcode project have had less use, and provisioning still involves a trip through Xcode. Expect to hit something; the fixes are usually in Xcode rather than in Joystick.

What you need

  • A Mac. iOS builds require Xcode, and Xcode is macOS-only.
  • Xcode, installed and opened at least once so it has finished setting itself up.
  • An Apple Developer account. The free tier is enough to run on your own device; a paid one is needed for TestFlight and the App Store.
  • Your device connected by cable, unlocked, and trusted for this Mac.

Setting it up

Open Settings → Build → Build Settings… and select the iOS platform.

Placeholder: the iOS pane of Build Settings, showing bundle identifier, app icon, Team ID and the export action

FieldWhat to put in it
Bundle IdentifierReverse-domain, unique to your game: com.yourstudio.yourgame. Changing it later makes iOS treat it as a different app, saves and all
App IconA single 1024×1024 .png. The engine generates every size iOS needs. Leave it blank to ship the template's placeholder icon
Team IDYour 10-character Apple Team ID. Press Detect to read it off a signing certificate already in your keychain. Leave it blank to generate an unsigned project you'll sign yourself in Xcode
ActionWhat the export does when it finishes — see below

The four actions

ActionWhat happens
Generate onlyProduces the Xcode project and stops. Take it from here yourself
Open project folderThe same, then reveals the folder in Finder
Build & run on deviceBuilds, signs, installs and launches on the device you pick. The one to use day to day
Archive .ipaProduces an .ipa for TestFlight or the App Store

With Build & run on device, a device dropdown appears — Refresh rescans for connected hardware. If your device isn't listed, it's usually locked, not trusted, or the cable is charge-only.

Your first run

  1. Set the bundle identifier and press Detect for the Team ID.
  2. Choose Build & run on device and pick your device.
  3. Export.

The first build is slow — it compiles the engine, your scripts and your assets for the device. Later builds reuse what hasn't changed.

If signing fails, the fastest route through it is Xcode: open the generated project, select the app target, and let Xcode's Automatically manage signing create the provisioning profile. That's a one-time step per bundle identifier per device.

Things that catch people out

"Untrusted Developer" when the app launches. With a free developer account, the device needs you to trust the certificate: Settings → General → VPN & Device Management → your developer profile → Trust.

The app expires after a week. Also a free-account limit — apps signed with a personal team stop working after seven days. Rebuild and reinstall, or use a paid account.

Performance is nothing like the editor. This is the whole point of testing on device. Build a Development build and use the on-screen profiler overlay — see The Profiler. Memory is the one that bites: iOS kills an app that goes over budget rather than slowing it down, so watch Memory.Available and act on Memory.PollPressure().

Safe areas. Notches and home indicators eat into the screen. Canvases have Apply Safe Area on by default; leave it on, and check the result on a device with a notch rather than in the editor.

Touch instead of keyboard. If your .jinput actions only have keyboard bindings, nothing will respond. Bind touch controls, and lay out on-screen controls in the Touch Controls Layout panel — see Input.

Before you submit

  • Every screen checked on a real device, in both orientations you support
  • App icon looked at on a home screen, not just in the build settings
  • Frame time and memory measured on the oldest device you claim to support
  • Saves confirmed to survive closing and reopening the app — see Saving and settings
  • If you support more than one language, the device language switched and checked

See also