diff --git a/ios/Fabric/RNCSafeAreaProviderComponentView.mm b/ios/Fabric/RNCSafeAreaProviderComponentView.mm index d16aea4a..910ebb68 100644 --- a/ios/Fabric/RNCSafeAreaProviderComponentView.mm +++ b/ios/Fabric/RNCSafeAreaProviderComponentView.mm @@ -17,6 +17,7 @@ @implementation RNCSafeAreaProviderComponentView { UIEdgeInsets _currentSafeAreaInsets; CGRect _currentFrame; BOOL _initialInsetsSent; + BOOL _registeredNotifications; } // Needed because of this: https://github.com/facebook/react-native/pull/37274 @@ -30,26 +31,39 @@ - (instancetype)initWithFrame:(CGRect)frame if (self = [super initWithFrame:frame]) { static const auto defaultProps = std::make_shared(); _props = defaultProps; - -#if !TARGET_OS_TV && !TARGET_OS_OSX - [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)willMoveToSuperview:(UIView *)newSuperView +{ + [super willMoveToSuperview:newSuperView]; + + if (newSuperView != nil && !_registeredNotifications) { + _registeredNotifications = YES; + [self registerNotifications]; + } +} + +- (void)registerNotifications +{ +#if !TARGET_OS_TV && !TARGET_OS_OSX + [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 +} + - (void)safeAreaInsetsDidChange { [self invalidateSafeAreaInsets]; @@ -57,6 +71,9 @@ - (void)safeAreaInsetsDidChange - (void)invalidateSafeAreaInsets { + if (self.superview == nil) { + return; + } // 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)) { @@ -123,6 +140,8 @@ - (void)prepareForRecycle _currentSafeAreaInsets = UIEdgeInsetsZero; _currentFrame = CGRectZero; _initialInsetsSent = NO; + [NSNotificationCenter.defaultCenter removeObserver:self]; + _registeredNotifications = NO; } @end