Why the menu is greyed out
Xcode's location simulation is a debugger feature. It sends a coordinate down the channel it already has open to the process it is attached to, which produces three failure modes that look like bugs and are not.
- Nothing is being debugged. The menu is enabled by the presence of a live session, so it goes flat the moment your app stops, including when it is killed by the watchdog, when you press stop out of habit, or when the app is launched from the home screen rather than from Xcode.
- The device is not the run destination. With a simulator selected in the scheme bar, the menu operates on the simulator. Plugging the phone in changes nothing until it is chosen as the destination and the app is run on it.
- It is not your app. Xcode can only move an app it launched under the debugger, from a scheme in the open project. There is no way to point the menu at Maps, at a colleague's TestFlight build, or at anything from the App Store.
A fourth case catches people occasionally: the menu is present and enabled but does nothing, because the app has an active location authorisation problem or is being debugged in a state where Core Location has not started. That is a genuine bug hunt. The three above are not, and no amount of cleaning derived data will change them.
The same service, without the project
The simulation itself is not implemented in Xcode. iOS exposes it as one of the instruments reachable through the device's developer services, the DVT channels that Instruments, the device console and Xcode all use. Xcode opens a channel to that service and sends a coordinate; the phone's Core Location stack starts returning it in place of the real fix.
Nothing about that arrangement requires a project. Any process on a trusted computer can open the same channel and send the same coordinate. Draftpin does exactly that, and the practical consequences are worth stating one by one, because each is a thing you would otherwise have to set up.
- No project and no scheme. Nothing is compiled and nothing is opened.
- No build. No install step, no launch, no watchdog to race.
- No Apple Developer account of your own. Nothing is installed on the device, so there is no provisioning profile to generate and no team to enrol in. Draftpin itself is signed and notarised on macOS, which is what lets it open without a Gatekeeper prompt, but that is our certificate and not something you need one of.
- No Mac required. Xcode implies macOS. This does not: Windows 10 and 11 are supported equally, with Apple's free Apple Devices app supplying the USB transport.
- Every app, not one. The fix is replaced device-wide rather than for a single debugged process.
On iOS 16 and newer the device needs Settings → Privacy & Security → Developer Mode switched on, followed by a restart. It gates the developer services on the phone and has nothing to do with a paid Apple Developer Program membership. What to do when the toggle is missing.
How it reaches the device
Everything runs over the cable, but Apple changed the transport twice in recent memory, and which path applies is decided entirely by the iOS version on the device. This is the part most tools do not explain, and it is the difference between a tool that needs elevation and one that does not.
- iOS 17.4 and newer: in-process userspace tunnel. The tunnel iOS requires is brought up inside the application's own process using a pure-Python network stack. There is no kernel interface to open, so no administrator rights and no UAC prompt. Since 17.4 shipped in March 2024, this is the path most devices take.
- iOS 17.0 to 17.3.1: privileged tunnel. Those releases predate the CoreDeviceProxy service that makes the in-process tunnel possible, and the fallback needs a privileged network interface. Draftpin detects the case and says so plainly rather than failing somewhere obscure. Updating the device to 17.4 or later is the fix.
- iOS 16 and older: lockdown and the Developer Disk Image. The older arrangement: talk to lockdown over usbmux, mount the Developer Disk Image if it is not already mounted, then open the instrument channel. No elevation involved.
One more version constraint sits underneath all of this. iOS 18.2 removed device-side QUIC support for the tunnel, and the TCP alternative is only the default on Python 3.13 and newer. Draftpin bundles a build new enough for that, which is not a detail you should ever have to think about, but it is the reason a hand-rolled environment on an older interpreter fails against a current iPhone in a way that looks like a hardware problem.
pymobiledevice3, already in the box
The library doing the device communication is pymobiledevice3 by
doronz88, and Draftpin bundles it along with the Python runtime it needs. There is
no pip install, no virtual environment, no PATH to repair and
no version of Python on your machine that can conflict with it. If you have previously
gone looking for how to install pymobiledevice3 on Windows, or hit a tool that told you
it was not installed, this is the answer to that: it is already there.
Internally the bundled component is a long-lived process rather than a command run per operation, and that is deliberate. The iOS 17.4-and-newer userspace tunnel exists only inside the process that created it and is not free to establish, so a per-call invocation would rebuild it on every position update. Holding the instrument channel open across many calls is the intended usage.
It also speaks newline-delimited JSON on stdio, which makes it usable on its own as a diagnostic when the application cannot see a device, because it isolates whether the problem is the device, the device layer, or the app around it.
$ .venv/bin/python -m draftpin_sidecar
{"id":1,"method":"list_devices"}
{"id":2,"method":"connect","params":{"udid":"<udid from step 1>"}}
{"id":3,"method":"set_location","params":{"latitude":40.690008,"longitude":-74.045843}}
{"id":4,"method":"clear_location"}
Every reply is one JSON line. Failures carry a machine-readable code and a remedy
rather than a stack trace: AMDS_MISSING, DEVICE_UNTRUSTED,
DEVELOPER_MODE_OFF, NEEDS_ELEVATED_TUNNEL and so on, each of which
is what lets the interface show a specific fix instead of a generic failure.
What each one means,
and what to do about it.
Scope, and the limits worth knowing
A device-wide simulated fix is more useful than a per-process one, and also blunter. Both facts matter for QA work.
The useful half: you can move an app you did not build. Checking how a competitor's store finder behaves in another country, reproducing a customer's bug in a shipped TestFlight build, capturing screenshots of your app somewhere photogenic. None of those are possible from the Xcode menu, and all of them are ordinary here.
The blunt half is worth reading before you leave it running.
-
Latitude and longitude, and nothing else. The selector is
simulateLocationWithLatitude:longitude:. Altitude and course cannot be transmitted by any tool, free or paid, because there is nowhere to put them. A heading derived from movement is shown in the interface but never sent, so an app readingcourseoraltitudefrom Core Location sees the device's own values, not yours. - It does not hide. There is no detection evasion of any kind, by design: no telemetry blocklists, no cooldown timers, no per-app workarounds. Apps that check whether a location is simulated will find out that it is.
- The cable stays in. There is no wireless mode. Unplugging restores the real fix immediately, which is a convenient undo and not an optional one.
- The Windows installer is not code-signed. SmartScreen warns on first run there. The Mac build is signed and notarised and opens without a prompt. Every build's SHA-256 is published either way, so you can verify what you downloaded.
Your existing Xcode GPX files still work
GPX files written for Xcode are ordinary GPX. In practice they tend to be a flat list
of <wpt> elements with no track wrapped around them, which some
importers reject because they look for a track and give up. Draftpin reads tracks and
routes first, and where a file contains neither it falls back to the standalone
waypoints, so the file already sitting in your project imports as a route without
being edited.
Once imported it behaves like any other route: play, pause, drag the progress bar to seek, watch the travelled portion shade in, and export it back out as GPX if you changed it. Speed and tick rate are set separately from the file rather than implied by timestamps inside it, which makes the same path replayable at walking pace and at 50 km/h without producing two files. The full guide to routes.
Xcode has one behaviour here that is worth a warning. Its location menu lists your custom GPX files alongside the built-in presets, City Run, Freeway Drive and the rest, and choosing one of those presets discards the custom GPX file you had selected. A stray click costs you the setup. Nothing equivalent happens in Draftpin: speed presets and routes are separate things, and picking one never removes the other.
Questions
Why is Simulate Location greyed out in Xcode?
Because nothing is being debugged. Debug → Simulate Location acts on the current debug session, so it only becomes available while an app you built is running on the device from a scheme in the open project. The three usual causes are: no session is active, the device is not selected as the run destination, or the app you want to move is one you did not build. None of them is a bug, and none is fixable from inside the menu.
Can I simulate a location on a real iPhone without Xcode?
Yes. The location-simulation service lives on the device, not in Xcode, and it is reachable over USB by any computer the phone trusts. Xcode is one client of it. Draftpin is another, and it speaks to the same service directly, so it needs no project, no scheme, no build and no debug session, just a cable and Developer Mode on iOS 16 and newer.
Does this need an Apple Developer account?
No. A paid account exists for signing and distributing code, and nothing here signs or installs anything on the device. Developer Mode on iOS 16 and newer is a toggle in Settings under Privacy & Security and is unrelated to enrolment. There is no account, no provisioning profile and no team ID involved at any point.
Does it affect every app or only mine?
Every app. The simulated location replaces the device's Core Location fix, so Maps, the weather, the Camera's geotagging and any third-party app all read it. Xcode's menu is scoped to the app under debug; this is not. That is useful when you need to check a competitor's behaviour or demo something you did not build, and worth remembering before you take a photograph.
Can I still use Xcode's GPX files?
Yes. The GPX files Xcode uses are ordinary GPX, usually a list of bare waypoint elements with no track around them. Draftpin's importer reads tracks and routes first and falls back to standalone waypoints when a file contains neither, which is exactly that shape. Import one and it becomes a route you can play, seek through and export again.
Get on with it
No project, no scheme, no build.
Free to start, for Windows and macOS. Python and pymobiledevice3 are bundled, so there is nothing to install alongside it.