Remove iOS 11 deprecation warnings around SafeArea (#32851)

Summary:
We don't have to check or emulate the safe area for iOS 11 above. I deleted the unnecessary check for the safe area.

This is a continuation pull request of these iOS 11 availability check.
* [Remove iOS 11 version check by ken0nek · Pull Request https://github.com/facebook/react-native/issues/32151 · facebook/react-native](https://github.com/facebook/react-native/pull/32151)
* [Remove iOS 11 availability check by ken0nek · Pull Request https://github.com/facebook/react-native/issues/32488 · facebook/react-native](https://github.com/facebook/react-native/pull/32488)

-----

- Stop using layout guide (`topLayoutGuide`, `bottomLayoutGuide`)
- Refactor `RCTSafeAreaView`
- Delete `emulateUnlessSupported` property

Docs PR: https://github.com/facebook/react-native-website/pull/2919

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[iOS] [Removed] - Remove `emulateUnlessSupported`

Pull Request resolved: https://github.com/facebook/react-native/pull/32851

Reviewed By: philIip, sammy-SC

Differential Revision: D33586023

Pulled By: cortinico

fbshipit-source-id: 75fc1037141f71d9340c7b875a6bf86f9cfd6a02
This commit is contained in:
Ken Tominaga
2022-05-16 09:27:43 -07:00
committed by Facebook GitHub Bot
parent c274456e5b
commit c73e021a4b
9 changed files with 23 additions and 157 deletions
@@ -9,7 +9,6 @@
*/
import type {ViewProps} from '../View/ViewPropTypes';
import type {WithDefault} from '../../Types/CodegenTypes';
import codegenNativeComponent from '../../Utilities/codegenNativeComponent';
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
@@ -17,8 +16,7 @@ import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
emulateUnlessSupported?: WithDefault<boolean, false>,
// No props
|}>;
export default (codegenNativeComponent<NativeProps>('SafeAreaView', {
@@ -12,18 +12,9 @@ import Platform from '../../Utilities/Platform';
import * as React from 'react';
import View from '../View/View';
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {ViewProps} from '../View/ViewPropTypes';
type Props = $ReadOnly<{|
...ViewProps,
emulateUnlessSupported?: boolean,
|}>;
let exported: React.AbstractComponent<
Props,
React.ElementRef<HostComponent<mixed>>,
>;
let exported: React.AbstractComponent<ViewProps, React.ElementRef<typeof View>>;
/**
* Renders nested content and automatically applies paddings reflect the portion
@@ -35,27 +26,9 @@ let exported: React.AbstractComponent<
* sensor housing area on iPhone X).
*/
if (Platform.OS === 'android') {
exported = React.forwardRef<Props, React.ElementRef<HostComponent<mixed>>>(
function SafeAreaView(props, forwardedRef) {
const {emulateUnlessSupported, ...localProps} = props;
return <View {...localProps} ref={forwardedRef} />;
},
);
exported = View;
} else {
const RCTSafeAreaViewNativeComponent =
require('./RCTSafeAreaViewNativeComponent').default;
exported = React.forwardRef<Props, React.ElementRef<HostComponent<mixed>>>(
function SafeAreaView(props, forwardedRef) {
return (
<RCTSafeAreaViewNativeComponent
emulateUnlessSupported={true}
{...props}
ref={forwardedRef}
/>
);
},
);
exported = require('./RCTSafeAreaViewNativeComponent').default;
}
export default exported;
@@ -1,9 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SafeAreaView /> should render as expected: should deep render when mocked (please verify output manually) 1`] = `
<RCTSafeAreaView
emulateUnlessSupported={true}
>
<RCTSafeAreaView>
<View>
<Text>
Hello World!
@@ -13,9 +11,7 @@ exports[`<SafeAreaView /> should render as expected: should deep render when moc
`;
exports[`<SafeAreaView /> should render as expected: should deep render when not mocked (please verify output manually) 1`] = `
<RCTSafeAreaView
emulateUnlessSupported={true}
>
<RCTSafeAreaView>
<View>
<Text>
Hello World!
@@ -25,21 +21,21 @@ exports[`<SafeAreaView /> should render as expected: should deep render when not
`;
exports[`<SafeAreaView /> should render as expected: should shallow render as <SafeAreaView /> when mocked 1`] = `
<ForwardRef(SafeAreaView)>
<RCTSafeAreaView>
<View>
<Text>
Hello World!
</Text>
</View>
</ForwardRef(SafeAreaView)>
</RCTSafeAreaView>
`;
exports[`<SafeAreaView /> should render as expected: should shallow render as <SafeAreaView /> when not mocked 1`] = `
<ForwardRef(SafeAreaView)>
<RCTSafeAreaView>
<View>
<Text>
Hello World!
</Text>
</View>
</ForwardRef(SafeAreaView)>
</RCTSafeAreaView>
`;
@@ -30,15 +30,6 @@ using namespace facebook::react;
return self;
}
- (UIEdgeInsets)_safeAreaInsets
{
if (@available(iOS 11.0, *)) {
return self.safeAreaInsets;
}
return UIEdgeInsetsZero;
}
- (void)safeAreaInsetsDidChange
{
[super safeAreaInsetsDidChange];
@@ -52,7 +43,7 @@ using namespace facebook::react;
return;
}
UIEdgeInsets insets = [self _safeAreaInsets];
UIEdgeInsets insets = self.safeAreaInsets;
insets.left = RCTRoundPixelValue(insets.left);
insets.top = RCTRoundPixelValue(insets.top);
insets.right = RCTRoundPixelValue(insets.right);
+9 -10
View File
@@ -16,11 +16,11 @@
@implementation RCTWrapperViewController {
UIView *_wrapperView;
UIView *_contentView;
CGFloat _previousTopLayoutLength;
CGFloat _previousBottomLayoutLength;
CGFloat _previousTopInset;
CGFloat _previousBottomInset;
id<UILayoutSupport> _currentTopLayoutGuide;
id<UILayoutSupport> _currentBottomLayoutGuide;
CGFloat _currentTopInset;
CGFloat _currentBottomInset;
}
- (instancetype)initWithContentView:(UIView *)contentView
@@ -41,8 +41,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
{
[super viewWillLayoutSubviews];
_currentTopLayoutGuide = self.topLayoutGuide;
_currentBottomLayoutGuide = self.bottomLayoutGuide;
_currentTopInset = self.view.safeAreaInsets.top;
_currentBottomInset = self.view.safeAreaInsets.bottom;
}
static BOOL RCTFindScrollViewAndRefreshContentInsetInView(UIView *view)
@@ -63,11 +63,10 @@ static BOOL RCTFindScrollViewAndRefreshContentInsetInView(UIView *view)
{
[super viewDidLayoutSubviews];
if (_previousTopLayoutLength != _currentTopLayoutGuide.length ||
_previousBottomLayoutLength != _currentBottomLayoutGuide.length) {
if (_previousTopInset != _currentTopInset || _previousBottomInset != _currentBottomInset) {
RCTFindScrollViewAndRefreshContentInsetInView(_contentView);
_previousTopLayoutLength = _currentTopLayoutGuide.length;
_previousBottomLayoutLength = _currentBottomLayoutGuide.length;
_previousTopInset = _currentTopInset;
_previousBottomInset = _currentBottomInset;
}
}
@@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithBridge:(RCTBridge *)bridge;
@property (nonatomic, assign) BOOL emulateUnlessSupported;
@end
NS_ASSUME_NONNULL_END
+2 -70
View File
@@ -21,7 +21,6 @@
{
if (self = [super initWithFrame:CGRectZero]) {
_bridge = bridge;
_emulateUnlessSupported = YES; // The default.
}
return self;
@@ -41,48 +40,10 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
return [NSString stringWithFormat:@"%@; safeAreaInsets = %@; appliedSafeAreaInsets = %@>",
superDescription,
NSStringFromUIEdgeInsets([self safeAreaInsetsIfSupportedAndEnabled]),
NSStringFromUIEdgeInsets(self.safeAreaInsets),
NSStringFromUIEdgeInsets(_currentSafeAreaInsets)];
}
- (BOOL)isSupportedByOS
{
return [self respondsToSelector:@selector(safeAreaInsets)];
}
- (UIEdgeInsets)safeAreaInsetsIfSupportedAndEnabled
{
if (self.isSupportedByOS) {
return self.safeAreaInsets;
}
return self.emulateUnlessSupported ? self.emulatedSafeAreaInsets : UIEdgeInsetsZero;
}
- (UIEdgeInsets)emulatedSafeAreaInsets
{
UIViewController *vc = self.reactViewController;
if (!vc) {
return UIEdgeInsetsZero;
}
CGFloat topLayoutOffset = vc.topLayoutGuide.length;
CGFloat bottomLayoutOffset = vc.bottomLayoutGuide.length;
CGRect safeArea = vc.view.bounds;
safeArea.origin.y += topLayoutOffset;
safeArea.size.height -= topLayoutOffset + bottomLayoutOffset;
CGRect localSafeArea = [vc.view convertRect:safeArea toView:self];
UIEdgeInsets safeAreaInsets = UIEdgeInsetsMake(0, 0, 0, 0);
if (CGRectGetMinY(localSafeArea) > CGRectGetMinY(self.bounds)) {
safeAreaInsets.top = CGRectGetMinY(localSafeArea) - CGRectGetMinY(self.bounds);
}
if (CGRectGetMaxY(localSafeArea) < CGRectGetMaxY(self.bounds)) {
safeAreaInsets.bottom = CGRectGetMaxY(self.bounds) - CGRectGetMaxY(localSafeArea);
}
return safeAreaInsets;
}
static BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIEdgeInsets insets2, CGFloat threshold)
{
return ABS(insets1.left - insets2.left) <= threshold && ABS(insets1.right - insets2.right) <= threshold &&
@@ -91,21 +52,7 @@ static BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIE
- (void)safeAreaInsetsDidChange
{
[self invalidateSafeAreaInsets];
}
- (void)invalidateSafeAreaInsets
{
[self setSafeAreaInsets:self.safeAreaInsetsIfSupportedAndEnabled];
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (!self.isSupportedByOS && self.emulateUnlessSupported) {
[self invalidateSafeAreaInsets];
}
[self setSafeAreaInsets:self.safeAreaInsets];
}
- (void)setSafeAreaInsets:(UIEdgeInsets)safeAreaInsets
@@ -120,19 +67,4 @@ static BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIE
[_bridge.uiManager setLocalData:localData forView:self];
}
- (void)setEmulateUnlessSupported:(BOOL)emulateUnlessSupported
{
if (_emulateUnlessSupported == emulateUnlessSupported) {
return;
}
_emulateUnlessSupported = emulateUnlessSupported;
if ([self isSupportedByOS]) {
return;
}
[self invalidateSafeAreaInsets];
}
@end
@@ -15,8 +15,6 @@
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(emulateUnlessSupported, BOOL)
- (UIView *)view
{
return [[RCTSafeAreaView alloc] initWithBridge:self.bridge];
@@ -18,7 +18,6 @@ const {
Modal,
SafeAreaView,
StyleSheet,
Switch,
Text,
View,
} = require('react-native');
@@ -27,12 +26,10 @@ class SafeAreaViewExample extends React.Component<
{...},
{|
modalVisible: boolean,
emulateUnlessSupported: boolean,
|},
> {
state = {
modalVisible: false,
emulateUnlessSupported: true,
};
_setModalVisible = visible => {
@@ -48,21 +45,12 @@ class SafeAreaViewExample extends React.Component<
animationType="slide"
supportedOrientations={['portrait', 'landscape']}>
<View style={styles.modal}>
<SafeAreaView
style={styles.safeArea}
emulateUnlessSupported={this.state.emulateUnlessSupported}>
<SafeAreaView style={styles.safeArea}>
<View style={styles.safeAreaContent}>
<Button
onPress={this._setModalVisible.bind(this, false)}
title="Close"
/>
<Text>emulateUnlessSupported:</Text>
<Switch
onValueChange={value =>
this.setState({emulateUnlessSupported: value})
}
value={this.state.emulateUnlessSupported}
/>
</View>
</SafeAreaView>
</View>
@@ -71,13 +59,6 @@ class SafeAreaViewExample extends React.Component<
onPress={this._setModalVisible.bind(this, true)}
title="Present Modal Screen with SafeAreaView"
/>
<Text>emulateUnlessSupported:</Text>
<Switch
onValueChange={value =>
this.setState({emulateUnlessSupported: value})
}
value={this.state.emulateUnlessSupported}
/>
</View>
);
}