-
-
Notifications
You must be signed in to change notification settings - Fork 630
enforceDesiredDeviceOrientation silently fails on iOS 16+ during screen transitions #3831
Description
Description
On iOS 16+, enforceDesiredDeviceOrientation in RNSScreenWindowTraits.mm has two bugs that cause per-screen orientation changes to silently fail during navigation transitions:
-
Stale
windowScene.interfaceOrientation— The heuristic checksinterfaceOrientationto decide whether rotation is needed. This value can be stale after scene restoration, app relaunch, or a previousrequestGeometryUpdatethat changed internal metadata without visually rotating. When stale, the method thinks the device is already in the correct orientation and skips the rotation entirely. (Same root cause as Orientation is not locked as intended #2197) -
Empty error handler on
requestGeometryUpdate— When called duringviewWillAppear, UIKit's internal orientation cache may still hold the outgoing screen's mask.requestGeometryUpdatevalidates against this stale cache and fails with:Error Domain=UISceneErrorDomain Code=101 "None of the requested orientations are supported by the view controller. Requested: portrait, portraitUpsideDown; Supported: landscapeRight"The error handler is
^(NSError *_Nonnull error){}— the failure is silently swallowed.
These bugs make it unreliable to navigate between screens with different orientations (e.g. portrait home → landscape play screen → back to portrait). After 1-2 cycles the orientation gets permanently stuck.
Related: expo/expo#43692, #2197, #1775
Steps to reproduce
- Clone the repro:
git clone https://github.com/JeanDes-Code/orientation-lock-repro npm install- Delete
patches/react-native-screens+4.23.0.patch(the expo-screen-orientation patch can stay — it's equivalent to expo/expo#44181) npm installagain (to revert the react-native-screens patch)npx expo prebuild --clean && npx expo run:ios- Tap "Go to Landscape (Option C)" — uses
Stack.Screen options={{ orientation: 'landscape_right' }} - Tap "Go Back" — screen should rotate to portrait but stays stuck in landscape
- Repeat — orientation locking fails in both directions
Snack or a link to a repository
https://github.com/JeanDes-Code/orientation-lock-repro
The repo includes a workaround patch for react-native-screens that:
- Always calls
setNeedsUpdateOfSupportedInterfaceOrientations+requestGeometryUpdateon iOS 16+ (bypasses the staleinterfaceOrientationheuristic) - Falls back to
UIDevice setValue:@(orientation) forKey:@"orientation"in the error handler - Moves the old heuristic to the pre-iOS 16 path only
Screens version
4.23.0
React Native version
0.83.4
Platforms
iOS
JavaScript runtime
Hermes
Workflow
Expo managed workflow
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
iOS simulator, Real device
Device model
iPhone 17 Pro Simulator (iOS 26.2), iPhone 15 Pro (iOS 18)
Acknowledgements
Yes