#import "RNCSafeAreaProviderComponentView.h" #import #import #import #import #import #import "RNCSafeAreaUtils.h" using namespace facebook::react; @interface RNCSafeAreaProviderComponentView () @end @implementation RNCSafeAreaProviderComponentView { UIEdgeInsets _currentSafeAreaInsets; CGRect _currentFrame; BOOL _initialInsetsSent; } - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { static const auto defaultProps = std::make_shared(); _props = defaultProps; #if !TARGET_OS_TV [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(invalidateSafeAreaInsets) name:UIKeyboardDidShowNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(invalidateSafeAreaInsets) name:UIKeyboardDidHideNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(invalidateSafeAreaInsets) name:UIKeyboardDidChangeFrameNotification object:nil]; #endif } return self; } - (void)safeAreaInsetsDidChange { [self invalidateSafeAreaInsets]; } - (void)invalidateSafeAreaInsets { // This gets called before the view size is set by react-native so // make sure to wait so we don't set wrong insets to JS. if (CGSizeEqualToSize(self.frame.size, CGSizeZero)) { return; } UIEdgeInsets safeAreaInsets = self.safeAreaInsets; CGRect frame = [self convertRect:self.bounds toView:nil]; if (_initialInsetsSent && UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) && CGRectEqualToRect(frame, _currentFrame)) { return; } _initialInsetsSent = YES; _currentSafeAreaInsets = safeAreaInsets; _currentFrame = frame; [NSNotificationCenter.defaultCenter postNotificationName:RNCSafeAreaDidChange object:self userInfo:nil]; if (_eventEmitter) { RNCSafeAreaProviderEventEmitter::OnInsetsChange event = { .insets = { .top = safeAreaInsets.top, .left = safeAreaInsets.left, .bottom = safeAreaInsets.bottom, .right = safeAreaInsets.right, }, .frame = { .x = frame.origin.x, .y = frame.origin.y, .width = frame.size.width, .height = frame.size.height, }, }; std::static_pointer_cast(_eventEmitter)->onInsetsChange(event); } } - (void)layoutSubviews { [super layoutSubviews]; [self invalidateSafeAreaInsets]; } #pragma mark - RCTComponentViewProtocol + (ComponentDescriptorProvider)componentDescriptorProvider { return concreteComponentDescriptorProvider(); } - (void)prepareForRecycle { [super prepareForRecycle]; _currentSafeAreaInsets = UIEdgeInsetsZero; _currentFrame = CGRectZero; _initialInsetsSent = NO; } @end Class RNCSafeAreaProviderCls(void) { return RNCSafeAreaProviderComponentView.class; }