The iOS Simulator Didn't Actually Disappear
If you upgraded to Xcode 27 and suddenly your old Expo or React Native workflow stopped launching the simulator, you're not alone.
Apple changed the way simulators are managed in Xcode 27. The standalone Simulator.app has been replaced by Device Hub, which now provides a central interface for simulated and physical devices. The simulator itself still exists β the management and launch workflow changed.
That distinction matters because older development tools were built around the old Simulator.app workflow.
And that's where things get interesting for React Native and Expo developers.
Why expo run:ios Can Break
Older versions of Expo CLI expected to find something like:
/Applications/Xcode.app/Contents/Developer/Applications/Simulator.appWith Xcode 27, that application is no longer there.
As a result, older Expo CLI versions could fail with errors such as:
CommandError: Can't determine id of Simulator appExpo tracked this as an Xcode 27 compatibility issue and subsequently added Device Hub support to the CLI. The React Native Community CLI also added Xcode 27 Device Hub support.
So npx expo run:ios isn't permanently broken.
The real issue is version compatibility between Xcode, Expo CLI, Expo SDK, and the native project.
If you're maintaining an older project that cannot immediately move to newer tooling, you may still hit the old Simulator.app problem.
What About Older Expo SDKs?
This is where things become messy.
An older Expo project may have:
- An older Expo CLI
- Older React Native tooling
- CocoaPods dependencies targeting old iOS versions
- Native modules that haven't caught up with Xcode 27
- Native configuration generated by an older Expo SDK
For example, the Expo issue tracker contains reports of SDK 55/56 projects encountering Xcode 27 problems, including the original Simulator.app lookup failure.
So if an old project suddenly stops working after an Xcode upgrade, don't immediately assume your JavaScript code is broken.
Sometimes the code is innocent.
The toolchain just decided to hold a funeral for your afternoon.
A Practical Workaround for Older Projects
If upgrading the Expo SDK isn't immediately possible, you can bypass the CLI's simulator-launching workflow and let Xcode handle the native application.
This was the workflow I used while working on an older Expo/React Native project.
1. Generate the Native iOS Project
From the Expo project:
npx expo prebuildThis gives you the native ios/ project and Podfile that you can open directly in Xcode.
2. Fix Old Pod Deployment Targets
One issue you may encounter with Xcode 27 is an old IPHONEOS_DEPLOYMENT_TARGET inside one of your CocoaPods dependencies.
If a pod is targeting an older iOS version, add the following to the post_install section of your Podfile:
# Force all pods to target a minimum of iOS 15.0
# for Xcode 27 compatibility
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 15.0
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
end
end
endThen install the pods again:
cd ios
pod installThis is particularly useful when an individual dependency or resource bundle still contains an older deployment target.
Note: if your project uses Expo Prebuild/CNG, manually editing generated native files can be overwritten when you regenerate the project. For a long-term solution, prefer Expo's supported native configuration where possible.
3. Open the Workspace in Xcode
Instead of asking Expo CLI to launch the simulator, open the Xcode workspace directly:
open ios/YourApp.xcworkspaceMake sure you open the .xcworkspace, not just the .xcodeproj, when you're using CocoaPods.
Then select your target device from Xcode's device selector and press Run.
Xcode handles the build and launches the application through Device Hub.
Apple's current documentation also uses Device Hub as the place to manage simulated and physical devices.
4. Running the App on Multiple Devices
This was one of the more useful things I discovered while working with the new workflow.
Suppose you want your app running on multiple devices at the same time.
Start by running the app on your first simulator or physical device from Xcode.
Once it's running:
Debug β Detach from <Your App Name>Detaching releases Xcode's debugger without shutting down the running application.
Then:
- Select another device from Xcode.
- Press Run again.
- Wait for the application to launch.
- Detach again.
- Repeat for additional devices.
You can end up with multiple instances of the same development build running simultaneously.
5. Connect Them All to Metro
Now comes the nice part for React Native.
Once the applications are running, start or restart Metro:
npx expo startIf Metro is already running, pressing:
rcan restart/reload the development server.
With the development clients connected, you can work on your React Native code while the running applications receive the JavaScript updates.
That means you can have something like:
Metro
β
ββββββββββββΌβββββββββββ
β β β
iPhone iPhone iPhone
#1 #2 #3This is particularly useful when testing:
- Different screen sizes
- Responsive layouts
- Device-specific behavior
- Navigation
- UI changes
- Platform-specific issues
You don't need to rebuild the native application every time you change a React component.
What About Expo Device Hub?
There is also an important distinction between Apple's Device Hub and Expo Device Hub.
Apple's Device Hub is part of Xcode 27 and manages Apple simulators and physical devices.
Expo also has an expo-device-hub DevTools plugin that provides a browser-based dashboard for controlling iOS simulators and Android emulators. Expo currently documents this plugin as requiring Expo SDK 57 or newer.
For example:
npx expo install expo-device-hubThen:
npx expo startThe Expo plugin provides features such as device streaming, interaction, boot/shutdown controls, and device management from the browser.
So don't confuse:
Apple Device Hubwith:
Expo Device HubThey're related in name, but they're different tools.
Should You Upgrade Your Expo Project?
If your project can be upgraded safely, using a current Expo SDK and current CLI is the better long-term approach.
Before changing anything, check your environment:
npx expo-doctorand:
xcodebuild -versionYou can also check your React Native environment with:
npx react-native infoIf you're on an older Expo SDK because of project dependencies or client requirements, the manual Xcode workflow can be a useful temporary bridge.
The important thing is to understand which layer is actually failing:
Xcode
β
iOS SDK
β
Expo CLI
β
Expo SDK
β
React Native
β
CocoaPods
β
Native modules
β
Your applicationChanging one layer doesn't automatically make the others compatible.
Final Takeaway
Xcode 27 didn't kill the iOS Simulator.
It changed how the simulator is managed.
The old workflow was roughly:
Expo CLI
β
Simulator.app
β
iOS SimulatorThe new Xcode 27 workflow is centered around:
Expo / Xcode
β
Device Hub
β
Simulators / Physical DevicesModern versions of Expo and the React Native Community CLI have added support for Device Hub, so the situation should improve as projects and tooling are updated.
But if you're maintaining an older Expo project today, the practical fallback is straightforward:
npx expo prebuildFix old Pod deployment targets if necessary, open:
ios/YourApp.xcworkspacerun the app directly through Xcode, use:
Debug β Detachto launch it on additional devices, and let Metro handle your React Native development loop.
So if expo run:ios suddenly gives you:
Can't determine id of Simulator appdon't panic.
Your app probably isn't dead.
Apple just moved the simulator while your CLI was still looking for it.