react-native-orientation-locker
react-native-orientation-locker copied to clipboard
fix ios 16 Setting UIDevice.orientation
BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)
#241
PS: Works on my end now, please update if you have any suggestions.
@ceddybi In my case, this change does not help, the screen orientation changes if I turn the phone.
This addresses the iOS 16 issue in our project, thanks for the fix!
@jfspencerAngel @ceddybi Before iOS 16, device orientation change notifies when locktolandscape or portrait but it is not working now(iOS 16) until rotate the device. something to do with setNeedsUpdateOfSupportedInterfaceOrientations ? https://developer.apple.com/documentation/uikit/uiviewcontroller/4047535-setneedsupdateofsupportedinterfa?language=objc
@ceddybi
Thank you for your PR
I suggest to apply below code, because UIDeviceOrientationDidChangeNotification couldn't detect orientation change when orientation changed via lockTo** method.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
[self addListener:@"orientationDidChange"];
I know UIApplicationWillChangeStatusBarOrientationNotification is deprecated from iOS13 but this library already used deprecated API like UIApplication.statusBarOrientation, so I just suggest it. unfortunately I'm not a specialist of iOS dev🥲,
If you know any alternative solution, I hope you feel free to use that
useEffect(() => { Orientation.addLockListener(onOrientationDidChange); // ios16 can full screen when orientation lanspage // Orientation.addOrientationListener(onOrientationDidChange); // ios16 not full screen , only 1/2 screen
return (() => {
Orientation.removeOrientationListener(onOrientationDidChange);
})
}, [])
I applied this my app, but even when setting lockToPortrait() the device will still rotate, anyway to prevent this?
can anyone please merge this changes.
can anyone please merge this changes.
I merged this branch in my fork, you can use a temporary solution in your package.json
"react-native-orientation-locker": "github:Soberones/react-native-orientation-locker",
Tested iOS 16.2 (simulator and real device)
I applied this my app, but even when setting lockToPortrait() the device will still rotate, anyway to prevent this?
Try to use only portrait in Xcode

Doesn't seem to fix anything if I patch the latest version (1.5.0) with this.
patching 1.5.0 works for me.
if it's not working, check your installation.
PITFALL: this part is not a part of manual linking, all methods need to do this https://github.com/wonday/react-native-orientation-locker#configuration
can anyone please merge this changes.
I merged this branch in my fork, you can use a temporary solution in your package.json
"react-native-orientation-locker": "github:Soberones/react-native-orientation-locker",Tested iOS 16.2 (simulator and real device)
not working with ios 15.5
https://github.com/wonday/react-native-orientation-locker#configuration
Doing the fix in the mentioned PR as a patch (i.e. patch-package) + applying the fixes suggested here worked for me
patch for version 1.5.0:
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
index 6117764..849387a 100644
--- a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
+++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
@@ -125,13 +125,19 @@ - (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UII
UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation;
[Orientation setOrientation:mask];
- UIDevice* currentDevice = [UIDevice currentDevice];
- [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
- [currentDevice setValue:@(newOrientation) forKey:orientation];
+ if (@available(iOS 16.0, *)) {
+ NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
+ UIWindowScene *scene = (UIWindowScene *)array[0]; UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask];
+ [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }];
+ } else {
+ UIDevice* currentDevice = [UIDevice currentDevice];
+ [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
+ [currentDevice setValue:@(newOrientation) forKey:orientation];
+ // restore device orientation
+ [currentDevice setValue:@(deviceOrientation) forKey:orientation];
+ }
- // restore device orientation
- [currentDevice setValue:@(deviceOrientation) forKey:orientation];
[UIViewController attemptRotationToDeviceOrientation];
Any update on merging the above PR
I tried to apply this fix but nothing changes in my case. But even after this patch i am able to go back to portrait mode from landscape mode but unable to lock orientation to portrait If anybody can help kindly respond I used this patch and this works somehow
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
index 6117764..c2658c5 100644
--- a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
+++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m
@@ -42,7 +42,8 @@ - (instancetype)init
_lastDeviceOrientation = (UIInterfaceOrientation) [UIDevice currentDevice].orientation;
_isLocking = NO;
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
[self addListener:@"orientationDidChange"];
}
return self;
@@ -116,6 +117,7 @@ - (NSString *)getOrientationStr: (UIInterfaceOrientation)orientation {
}
return orientationStr;
}
+// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
- (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UIInterfaceOrientationMask) mask {
// set a flag so that no deviceOrientationDidChange events are sent to JS
@@ -125,13 +127,24 @@ - (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UII
UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation;
[Orientation setOrientation:mask];
- UIDevice* currentDevice = [UIDevice currentDevice];
-
- [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
- [currentDevice setValue:@(newOrientation) forKey:orientation];
+ // UIDevice* currentDevice = [UIDevice currentDevice];
+
+ // [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
+ // [currentDevice setValue:@(newOrientation) forKey:orientation];
+
+ if (@available(iOS 16.0, *)) {
+ NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
+ UIWindowScene *scene = (UIWindowScene *)array[0];
+ UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask];
+ [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }];
+ } else {
+ UIDevice* currentDevice = [UIDevice currentDevice];
+ [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
+ [currentDevice setValue:@(newOrientation) forKey:orientation];
+ }
// restore device orientation
- [currentDevice setValue:@(deviceOrientation) forKey:orientation];
+ // [currentDevice setValue:@(deviceOrientation) forKey:orientation];
[UIViewController attemptRotationToDeviceOrientation];
also in ios/{projectName}/AppDelegate.mm i added
if (@available(iOS 16.0, *)) {
NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
UIWindowScene *scene = (UIWindowScene *)array[0];
UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask];
[scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }];
} else {
UIDevice* currentDevice = [UIDevice currentDevice];
[currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
[currentDevice setValue:@(newOrientation) forKey:orientation];
}
but even after this patch i am able to go back to portrait mode from landscape mode but unable to lock orientation to portrait
https://github.com/wonday/react-native-orientation-locker#configuration
Doing the fix in the mentioned PR as a patch (i.e. patch-package) + applying the fixes suggested here worked for me
patch for version 1.5.0:
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m index 6117764..849387a 100644 --- a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m +++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m @@ -125,13 +125,19 @@ - (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UII UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation; [Orientation setOrientation:mask]; - UIDevice* currentDevice = [UIDevice currentDevice]; - [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; - [currentDevice setValue:@(newOrientation) forKey:orientation]; + if (@available(iOS 16.0, *)) { + NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects]; + UIWindowScene *scene = (UIWindowScene *)array[0]; UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask]; + [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }]; + } else { + UIDevice* currentDevice = [UIDevice currentDevice]; + [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; + [currentDevice setValue:@(newOrientation) forKey:orientation]; + // restore device orientation + [currentDevice setValue:@(deviceOrientation) forKey:orientation]; + } - // restore device orientation - [currentDevice setValue:@(deviceOrientation) forKey:orientation]; [UIViewController attemptRotationToDeviceOrientation];
This works. 👍🏻
https://github.com/wonday/react-native-orientation-locker#configuration
Doing the fix in the mentioned PR as a patch (i.e. patch-package) + applying the fixes suggested here worked for me patch for version 1.5.0:
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m index 6117764..849387a 100644 --- a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m +++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m @@ -125,13 +125,19 @@ - (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UII UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation; [Orientation setOrientation:mask]; - UIDevice* currentDevice = [UIDevice currentDevice]; - [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; - [currentDevice setValue:@(newOrientation) forKey:orientation]; + if (@available(iOS 16.0, *)) { + NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects]; + UIWindowScene *scene = (UIWindowScene *)array[0]; UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask]; + [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }]; + } else { + UIDevice* currentDevice = [UIDevice currentDevice]; + [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; + [currentDevice setValue:@(newOrientation) forKey:orientation]; + // restore device orientation + [currentDevice setValue:@(deviceOrientation) forKey:orientation]; + } - // restore device orientation - [currentDevice setValue:@(deviceOrientation) forKey:orientation]; [UIViewController attemptRotationToDeviceOrientation];This works. 👍🏻
I applied same changes.But still screen doesn't rotate to LANDSCAPE mode. Surprising thing is LANDSCAPE orientation is working as expected in debug mode without applying above changes. But not working in release mode even after applying above changes.
Am i missing anything here?
Hi. This is 2024 and I still face error: BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:) on iOS
I followed this pull request and updated Orientation.m in "react-native-orientation-locker": "^1.6.0" but it still isn't working?
Does anyone have a solution for it?
@@ -138,10 +138,17 @@ static UIInterfaceOrientationMask _orientationMask = UIInterfaceOrientationMaskA
UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation;
[Orientation setOrientation:mask];
- UIDevice* currentDevice = [UIDevice currentDevice];
- [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
- [currentDevice setValue:@(newOrientation) forKey:orientation];
+ if (@available(iOS 16.0, *)) {
+ NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
+ UIWindowScene *scene = (UIWindowScene *)array[0];
+ UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask];
+ [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }];
+ } else {
+ UIDevice* currentDevice = [UIDevice currentDevice];
+ [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation];
+ [currentDevice setValue:@(newOrientation) forKey:orientation];
+ }
[UIViewController attemptRotationToDeviceOrientation];
@@ -168,8 +175,7 @@ RCT_EXPORT_METHOD(configure:(NSDictionary *)options)
Hi. This is 2024 and I still face error: BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:) on iOS I followed this pull request and updated
Orientation.min"react-native-orientation-locker": "^1.6.0"but it still isn't working? Does anyone have a solution for it?@@ -138,10 +138,17 @@ static UIInterfaceOrientationMask _orientationMask = UIInterfaceOrientationMaskA UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation; [Orientation setOrientation:mask]; - UIDevice* currentDevice = [UIDevice currentDevice]; - [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; - [currentDevice setValue:@(newOrientation) forKey:orientation]; + if (@available(iOS 16.0, *)) { + NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects]; + UIWindowScene *scene = (UIWindowScene *)array[0]; + UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask]; + [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }]; + } else { + UIDevice* currentDevice = [UIDevice currentDevice]; + [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; + [currentDevice setValue:@(newOrientation) forKey:orientation]; + } [UIViewController attemptRotationToDeviceOrientation]; @@ -168,8 +175,7 @@ RCT_EXPORT_METHOD(configure:(NSDictionary *)options)
This has been implemented as of release 1.7.0, however, lockToPortrait() and lockToLandscape() do not rotate the view (at least in the simulator like it does for Android). I was expecting this to do so.
I still get
[UIKitCore] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported.
Please use UIWindowScene.requestGeometryUpdate(_:)
Am I wrong in my expectation?
Hi. This is 2024 and I still face error: BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:) on iOS I followed this pull request and updated
Orientation.min"react-native-orientation-locker": "^1.6.0"but it still isn't working? Does anyone have a solution for it?@@ -138,10 +138,17 @@ static UIInterfaceOrientationMask _orientationMask = UIInterfaceOrientationMaskA UIInterfaceOrientation deviceOrientation = _lastDeviceOrientation; [Orientation setOrientation:mask]; - UIDevice* currentDevice = [UIDevice currentDevice]; - [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; - [currentDevice setValue:@(newOrientation) forKey:orientation]; + if (@available(iOS 16.0, *)) { + NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects]; + UIWindowScene *scene = (UIWindowScene *)array[0]; + UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:mask]; + [scene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) { }]; + } else { + UIDevice* currentDevice = [UIDevice currentDevice]; + [currentDevice setValue:@(UIInterfaceOrientationUnknown) forKey:orientation]; + [currentDevice setValue:@(newOrientation) forKey:orientation]; + } [UIViewController attemptRotationToDeviceOrientation]; @@ -168,8 +175,7 @@ RCT_EXPORT_METHOD(configure:(NSDictionary *)options)This has been implemented as of release 1.7.0, however, lockToPortrait() and lockToLandscape() do not rotate the view (at least in the simulator like it does for Android). I was expecting this to do so.
I still get
[UIKitCore] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)Am I wrong in my expectation?
Same, I'm somewhat confused here. I could enable Landscape Left and Landscape Right, but lockToPortrait() is not working so the user is able to change orientation all across the application