Skip to content

Commit

Permalink
fix: use new rotation API for iOS 16 (#1732)
Browse files Browse the repository at this point in the history
## Description

Fixes:

> [Orientation] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is
not supported. Please use UIWindowScene.requestGeometryUpdate(_:)

for iOS 16+.

Changes were inspired by these threads:
- https://developer.apple.com/forums/thread/707735
- https://developer.apple.com/forums/thread/709215
- https://stackoverflow.com/a/73735976/9272042

## Changes

- added usage of new API for rotation management for iOS 16+ in
`RNSScreenWindowTraits.mm`;

## Screenshots / GIFs

### Before


https://user-images.githubusercontent.com/22820318/223976297-8cb1733d-6611-4d23-aed1-e659fadf6b09.mov

## Test code and steps to reproduce

Just test a scenario when `enforceDesiredDeviceOrientation` is called on
iOS 16. Every time when you call

```objc
[[UIDevice currentDevice] setValue:@(newOrientation) forKey:@"orientation"];
```

You will see a warning in XCode logger. If you rotate screen there may
be a possibility that sometimes layout will be broken.

## Checklist

- [x] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation: <!-- For adding new props to native-stack
-->
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [x] Ensured that CI passes
  • Loading branch information
kirillzyusko authored Apr 12, 2023
1 parent 13a72f8 commit b9239d8
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions ios/RNSScreenWindowTraits.mm
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,27 @@ + (void)enforceDesiredDeviceOrientation
}
}
if (newOrientation != UIInterfaceOrientationUnknown) {
[[UIDevice currentDevice] setValue:@(newOrientation) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
if (@available(iOS 16.0, *)) {
NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
UIWindowScene *scene = (UIWindowScene *)array[0];
UIWindowSceneGeometryPreferencesIOS *geometryPreferences =
[[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientationMask];
[scene requestGeometryUpdateWithPreferences:geometryPreferences
errorHandler:^(NSError *_Nonnull error){
}];

// `attemptRotationToDeviceOrientation` is deprecated for modern OS versions
// so we need to use `setNeedsUpdateOfSupportedInterfaceOrientations`
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}

[topController setNeedsUpdateOfSupportedInterfaceOrientations];
} else {
[[UIDevice currentDevice] setValue:@(newOrientation) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
}
});
#endif
Expand Down

0 comments on commit b9239d8

Please sign in to comment.