diff --git a/packages/react-native/React/Base/UIKitProxies/RCTInitializeUIKitProxies.mm b/packages/react-native/React/Base/UIKitProxies/RCTInitializeUIKitProxies.mm index aaf443ef7bf..d82ee2ead5b 100644 --- a/packages/react-native/React/Base/UIKitProxies/RCTInitializeUIKitProxies.mm +++ b/packages/react-native/React/Base/UIKitProxies/RCTInitializeUIKitProxies.mm @@ -7,7 +7,6 @@ #import "RCTInitializeUIKitProxies.h" #import "RCTInitialAccessibilityValuesProxy.h" -#import "RCTKeyWindowValuesProxy.h" #import "RCTTraitCollectionProxy.h" #import "RCTWindowSafeAreaProxy.h" @@ -18,6 +17,5 @@ void RCTInitializeUIKitProxies(void) [[RCTWindowSafeAreaProxy sharedInstance] startObservingSafeArea]; [[RCTTraitCollectionProxy sharedInstance] startObservingTraitCollection]; [[RCTInitialAccessibilityValuesProxy sharedInstance] recordAccessibilityValues]; - [[RCTKeyWindowValuesProxy sharedInstance] startObservingWindowSizeIfNecessary]; }); } diff --git a/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.h b/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.h deleted file mode 100644 index 0723389c5b0..00000000000 --- a/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface RCTKeyWindowValuesProxy : NSObject - -+ (instancetype)sharedInstance; - -@property (assign, readonly) CGSize windowSize; -@property (assign, readonly) UIInterfaceOrientation currentInterfaceOrientation; - -- (void)startObservingWindowSizeIfNecessary; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.mm b/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.mm deleted file mode 100644 index bbf118c8a1a..00000000000 --- a/packages/react-native/React/Base/UIKitProxies/RCTKeyWindowValuesProxy.mm +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTKeyWindowValuesProxy.h" -#import -#import -#import - -#import - -static NSString *const kFrameKeyPath = @"frame"; - -@implementation RCTKeyWindowValuesProxy { - BOOL _isObserving; - std::mutex _mutex; - CGSize _currentWindowSize; - UIInterfaceOrientation _currentInterfaceOrientation; -} - -+ (instancetype)sharedInstance -{ - static RCTKeyWindowValuesProxy *sharedInstance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedInstance = [RCTKeyWindowValuesProxy new]; - }); - return sharedInstance; -} - -- (instancetype)init -{ - self = [super init]; - if (self) { - _isObserving = NO; - UIView *mainWindow = RCTKeyWindow(); - _currentWindowSize = mainWindow ? mainWindow.bounds.size : UIScreen.mainScreen.bounds.size; - } - return self; -} - -- (void)startObservingWindowSizeIfNecessary -{ - // Accesing _isObserving must be done under the lock to avoid a race condition. - // We can't hold the lock while calling RCTUnsafeExecuteOnMainQueueSync. - // Therefore, reading/writing _isObserving is kept separate from calling RCTUnsafeExecuteOnMainQueueSync. - { - std::lock_guard lock(_mutex); - if (_isObserving) { - return; - } - _isObserving = YES; - } - - // For backwards compatibility, we register for notifications from the main thread only. - // On the new architecture, we are already on the main thread and RCTUnsafeExecuteOnMainQueueSync will simply call - // the block. - RCTUnsafeExecuteOnMainQueueSync(^{ - [RCTKeyWindow() addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; - }); - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_interfaceOrientationDidChange) - name:UIApplicationDidBecomeActiveNotification - object:nil]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if ([keyPath isEqualToString:kFrameKeyPath]) { - [[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self]; - { - std::lock_guard lock(_mutex); - _currentWindowSize = RCTKeyWindow().bounds.size; - } - } -} - -- (CGSize)windowSize -{ - { - std::lock_guard lock(_mutex); - if (_isObserving) { - return _currentWindowSize; - } - } - - __block CGSize size; - RCTUnsafeExecuteOnMainQueueSync(^{ - size = RCTKeyWindow().bounds.size; - }); - return size; -} - -- (UIInterfaceOrientation)currentInterfaceOrientation -{ - { - std::lock_guard lock(_mutex); - if (_isObserving) { - return _currentInterfaceOrientation; - } - } - - __block UIInterfaceOrientation interfaceOrientation; - RCTUnsafeExecuteOnMainQueueSync(^{ - interfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; - }); - return interfaceOrientation; -} - -- (void)_interfaceOrientationDidChange -{ - std::lock_guard lock(_mutex); - _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; -} - -@end diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index 8761904c55b..193e97448de 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -14,9 +14,7 @@ #import #import #import -#import #import -#import #import #import "CoreModulesPlugins.h" @@ -33,6 +31,8 @@ using namespace facebook::react; std::atomic _invalidated; } +static NSString *const kFrameKeyPath = @"frame"; + @synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -40,14 +40,25 @@ RCT_EXPORT_MODULE() - (instancetype)init { if (self = [super init]) { - [[RCTKeyWindowValuesProxy sharedInstance] startObservingWindowSizeIfNecessary]; + [RCTKeyWindow() addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; } return self; } +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + if ([keyPath isEqualToString:kFrameKeyPath]) { + [self interfaceFrameDidChange]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self]; + } +} + + (BOOL)requiresMainQueueSetup { - return NO; + return YES; } - (dispatch_queue_t)methodQueue @@ -81,7 +92,7 @@ RCT_EXPORT_MODULE() #if TARGET_OS_IOS - _currentInterfaceOrientation = [RCTKeyWindowValuesProxy sharedInstance].currentInterfaceOrientation; + _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) @@ -120,6 +131,8 @@ RCT_EXPORT_MODULE() [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; + [RCTKeyWindow() removeObserver:self forKeyPath:kFrameKeyPath]; + #if TARGET_OS_IOS [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; #endif @@ -132,8 +145,13 @@ static BOOL RCTIsIPhoneNotched() #if TARGET_OS_IOS dispatch_once(&onceToken, ^{ + RCTAssertMainQueue(); + // 20pt is the top safeArea value in non-notched devices - isIPhoneNotched = [RCTWindowSafeAreaProxy sharedInstance].currentSafeAreaInsets.top > 20; + UIWindow *keyWindow = RCTKeyWindow(); + if (keyWindow) { + isIPhoneNotched = keyWindow.safeAreaInsets.top > 20; + } }); #endif @@ -142,11 +160,13 @@ static BOOL RCTIsIPhoneNotched() static NSDictionary *RCTExportedDimensions(CGFloat fontScale) { + RCTAssertMainQueue(); UIScreen *mainScreen = UIScreen.mainScreen; CGSize screenSize = mainScreen.bounds.size; + UIView *mainWindow = RCTKeyWindow(); // We fallback to screen size if a key window is not found. - CGSize windowSize = [RCTKeyWindowValuesProxy sharedInstance].windowSize; + CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize; NSDictionary *dimsWindow = @{ @"width" : @(windowSize.width), @@ -182,14 +202,20 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) - (NSDictionary *)getConstants { - return @{ - @"Dimensions" : [self _exportedDimensions], - // Note: - // This prop is deprecated and will be removed in a future release. - // Please use this only for a quick and temporary solution. - // Use instead. - @"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()), - }; + __block NSDictionary *constants; + __weak __typeof(self) weakSelf = self; + RCTUnsafeExecuteOnMainQueueSync(^{ + constants = @{ + @"Dimensions" : [weakSelf _exportedDimensions], + // Note: + // This prop is deprecated and will be removed in a future release. + // Please use this only for a quick and temporary solution. + // Use instead. + @"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()), + }; + }); + + return constants; } - (void)didReceiveNewContentSizeMultiplier