From 917f539b182d45d4f77b7fad0d1dec3301c84b5b Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 08:30:36 +0200 Subject: [PATCH 1/6] feat: migrate to SceneDelegate, update RNTester code --- .../AppDelegate/RCTReactNativeFactory.h | 23 ++ .../AppDelegate/RCTReactNativeFactory.mm | 74 ++++- .../Libraries/LinkingIOS/RCTLinkingManager.h | 20 ++ .../Libraries/LinkingIOS/RCTLinkingManager.mm | 99 +++++-- packages/react-native/React/Base/RCTUtils.h | 3 + packages/react-native/React/Base/RCTUtils.mm | 18 ++ .../React/CoreModules/RCTDeviceInfo.mm | 43 ++- packages/rn-tester/Podfile | 4 + packages/rn-tester/Podfile.lock | 184 +++++++----- packages/rn-tester/RNTester/AppDelegate.h | 12 + packages/rn-tester/RNTester/AppDelegate.mm | 6 + packages/rn-tester/RNTester/SceneDelegate.h | 27 ++ packages/rn-tester/RNTester/SceneDelegate.mm | 102 +++++++ .../RNTesterPods.xcodeproj/project.pbxproj | 280 +++++++++++++++++- 14 files changed, 774 insertions(+), 121 deletions(-) create mode 100644 packages/rn-tester/RNTester/SceneDelegate.h create mode 100644 packages/rn-tester/RNTester/SceneDelegate.mm diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h index 14304a97eb99..105d45e1a2e1 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h @@ -101,6 +101,29 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable }; initialProperties:(NSDictionary *_Nullable)initialProperties launchOptions:(NSDictionary *_Nullable)launchOptions; +/// This is a SceneDelegate entrypoint method to start a React Native instance with the specified module name, window +/// and connection options for linking & user activity information. As it's usual for the typical deep-linking use case, +/// only the first item in URLContexts from connectionOptions will be checked; the same applies to userActivities. +/// @param moduleName name of the JS module to load +/// @param window the window to launch in +/// @param connectionOptions the scene's connection options +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + connectionOptions:(UISceneConnectionOptions *_Nullable)connectionOptions; + +/// This is a SceneDelegate entrypoint method to start a React Native instance with the specified module name, window +/// and connection options for linking, initial properties & user activity information. As it's usual for the typical +/// deep-linking use case, only the first item in URLContexts from connectionOptions will be checked; the same applies +/// to userActivities. +/// @param moduleName name of the JS module to load +/// @param window the window to launch in +/// @param initialProperties the initial root properties +/// @param connectionOptions the scene's connection options +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + initialProperties:(NSDictionary *_Nullable)initialProperties + connectionOptions:(UISceneConnectionOptions *_Nullable)connectionOptions; + @property (nonatomic, nullable) RCTBridge *bridge; @property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm index 9d5a45787af0..b0cebc50bc08 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm @@ -32,11 +32,30 @@ using namespace facebook::react; +@interface DeallocationNotifier : NSObject +@property (nonatomic, copy) void (^onDealloc)(void); +@end + +@implementation DeallocationNotifier +- (void)dealloc +{ + if (self.onDealloc) + self.onDealloc(); +} +@end + @interface RCTReactNativeFactory () < RCTComponentViewFactoryComponentProvider, RCTHostDelegate, RCTJSRuntimeConfiguratorProtocol, RCTTurboModuleManagerDelegate> + +/// Adapter for SceneDelegate entrypoint's UISceneConnectionOptions that converts it to the AppDelegate-style +/// NSDictionary for internal RN needs +/// @param connectionOptions the scene's connection options +/// @return an NSDictionary with proper UIApplicationLaunchOptions- keys set to values from connectionOptions +- (NSDictionary *)convertConnectionOptionsToLaunchOptions:(UISceneConnectionOptions *)connectionOptions; + @end @implementation RCTReactNativeFactory @@ -89,6 +108,58 @@ - (void)startReactNativeWithModuleName:(NSString *)moduleName [window makeKeyAndVisible]; } +#pragma mark - UIScene.ConnectionOptions + +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + connectionOptions:(UISceneConnectionOptions *_Nullable)connectionOptions +{ + [self startReactNativeWithModuleName:moduleName + inWindow:window + initialProperties:nil + launchOptions:[self convertConnectionOptionsToLaunchOptions:connectionOptions]]; +} + +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + initialProperties:(NSDictionary *_Nullable)initialProperties + connectionOptions:(UISceneConnectionOptions *_Nullable)connectionOptions +{ + [self startReactNativeWithModuleName:moduleName + inWindow:window + initialProperties:initialProperties + launchOptions:[self convertConnectionOptionsToLaunchOptions:connectionOptions]]; +} + +- (NSDictionary *)convertConnectionOptionsToLaunchOptions:(UISceneConnectionOptions *)connectionOptions +{ + NSMutableDictionary *launchOptions = [NSMutableDictionary dictionary]; + + // handle launch URL + if (connectionOptions.URLContexts.count > 0) { + UIOpenURLContext *urlContext = connectionOptions.URLContexts.allObjects.firstObject; + + if (urlContext.URL) { + launchOptions[UIApplicationLaunchOptionsURLKey] = urlContext.URL; + } + } + + // handle user activities + if (connectionOptions.userActivities.count > 0) { + NSUserActivity *activity = connectionOptions.userActivities.allObjects.firstObject; + + if (activity) { + NSMutableDictionary *userActivityDict = [NSMutableDictionary dictionary]; + userActivityDict[UIApplicationLaunchOptionsUserActivityTypeKey] = activity.activityType; + userActivityDict[@"UIApplicationLaunchOptionsUserActivityKey"] = activity; + + launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] = userActivityDict; + } + } + + return launchOptions; +} + #pragma mark - RCTUIConfiguratorProtocol - (RCTColorSpace)defaultColorSpace @@ -188,7 +259,8 @@ - (Class)getModuleClassFromName:(const char *)name return moduleInstance; } } - return RCTAppSetupDefaultModuleFromClass(moduleClass, self.delegate.dependencyProvider); + return RCTAppSetupDefaultModuleFromClass( + moduleClass, self.delegate.dependencyProvider); } - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h index eff3b0c54614..4e9b7e8da417 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.h @@ -11,17 +11,37 @@ @interface RCTLinkingManager : RCTEventEmitter +#pragma mark - AppDelegate methods + +/// Lifecycle method informing of a URL being opened with the app, must be invoked from the AppDelegate. +/// Must be invoked from the AppDelegate. +/// Note: this is an implementation using the iOS 9.0-26.0 API + (BOOL)application:(nonnull UIApplication *)app openURL:(nonnull NSURL *)URL options:(nonnull NSDictionary *)options; +/// Lifecycle method handling a URL being opened with the app, must be invoked from the AppDelegate. +/// Must be invoked from the AppDelegate. +/// Note: this is an implementation using the iOS 4.2-9.0 API + (BOOL)application:(nonnull UIApplication *)application openURL:(nonnull NSURL *)URL sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation; +/// Lifecycle method handling user activity being performed. +/// Must be invoked from the AppDelegate. + (BOOL)application:(nonnull UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> *_Nullable))restorationHandler; +#pragma mark - SceneDelegate methods + +/// Successor to AppDelegate's application:continueUserActivity:restorationHandler:, which handles user activity being +/// performed. Must be invoked from the SceneDelegate. ++ (void)scene:(nonnull UIScene *)scene continueUserActivity:(nonnull NSUserActivity *)userActivity; + +/// Successor to AppDelegate's application:openURL:options:, which handles user activity being performed. +/// Must be invoked from the SceneDelegate. ++ (void)scene:(nonnull UIScene *)scene openURLContexts:(nonnull NSSet *)URLContexts; + @end diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm index ad75ed482c49..7356b73523e2 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm @@ -16,24 +16,38 @@ static NSString *const kOpenURLNotification = @"RCTOpenURLNotification"; -static void postNotificationWithURL(NSURL *URL, id sender) -{ - NSDictionary *payload = @{@"url" : URL.absoluteString}; - [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:sender userInfo:payload]; -} - @interface RCTLinkingManager () + +/// Common logic for handling user activities originating from both AppDelegate- and SceneDelegate- lifecycle methods ++ (void)handleUserActivity:(NSUserActivity *)userActivity window:(UIWindow *)window; + +/// Common logic for handling user activities from AppDelegate-lifecycle methods. ++ (BOOL)handleAppDelegateURL:(NSURL *)URL app:(UIApplication *)app; + +/// Posts a URL notification that will be handled by the emitter to JS; this method is used to invoke instance methods +/// of RCTLinkingManager from class methods via NSNotificationCenter. +/// @param URL The URL to be emitted. ++ (void)postNotificationWithURL:(NSURL *)URL; + @end @implementation RCTLinkingManager RCT_EXPORT_MODULE() ++ (void)postNotificationWithURL:(NSURL *)URL +{ + NSDictionary *payload = @{@"url" : URL.absoluteString}; + [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:nil userInfo:payload]; +} + - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } +#pragma mark - RCTEventEmitter methods + - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self @@ -52,34 +66,70 @@ - (void)stopObserving return @[ @"url" ]; } +#pragma mark - JS methods + + (BOOL)application:(UIApplication *)app openURL:(NSURL *)URL options:(NSDictionary *)options { - postNotificationWithURL(URL, self); - return YES; + return [self handleAppDelegateURL:URL app:app]; } -// Corresponding api deprecated in iOS 9 + (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { - postNotificationWithURL(URL, self); - return YES; + return [self handleAppDelegateURL:URL app:application]; } + (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> *_Nullable))restorationHandler +{ + if (!RCTIsSceneDelegateApp()) { + [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindow()]; + return YES; + } + + return NO; +} + +#pragma mark - SceneDelegate methods + ++ (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity +{ + [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindow()]; +} + ++ (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts +{ + if (URLContexts.count == 0) { + return; + } + + NSURL *URL = URLContexts.allObjects.firstObject.URL; + [RCTLinkingManager postNotificationWithURL:URL]; +} + +#pragma mark - Common logic methods + ++ (void)handleUserActivity:(NSUserActivity *)userActivity window:(UIWindow *)window { // This can be nullish when launching an App Clip. if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && userActivity.webpageURL != nil) { - NSDictionary *payload = @{@"url" : userActivity.webpageURL.absoluteString}; - [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:self userInfo:payload]; + [RCTLinkingManager postNotificationWithURL:userActivity.webpageURL]; } - return YES; +} + ++ (BOOL)handleAppDelegateURL:(NSURL *)URL app:(UIApplication *)app +{ + if (!RCTIsSceneDelegateApp()) { + [RCTLinkingManager postNotificationWithURL:URL]; + return YES; + } + + return NO; } - (void)handleOpenURLNotification:(NSNotification *)notification @@ -87,10 +137,10 @@ - (void)handleOpenURLNotification:(NSNotification *)notification [self sendEventWithName:@"url" body:notification.userInfo]; } -RCT_EXPORT_METHOD(openURL - : (NSURL *)URL resolve - : (RCTPromiseResolveBlock)resolve reject - : (RCTPromiseRejectBlock)reject) +#pragma mark - JS methods + +RCT_EXPORT_METHOD(openURL : (NSURL *)URL resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock) + reject) { [RCTSharedApplication() openURL:URL options:@{} @@ -114,10 +164,8 @@ - (void)handleOpenURLNotification:(NSNotification *)notification }]; } -RCT_EXPORT_METHOD(canOpenURL - : (NSURL *)URL resolve - : (RCTPromiseResolveBlock)resolve reject - : (__unused RCTPromiseRejectBlock)reject) +RCT_EXPORT_METHOD(canOpenURL : (NSURL *)URL resolve : (RCTPromiseResolveBlock) + resolve reject : (__unused RCTPromiseRejectBlock)reject) { if (RCTRunningInAppExtension()) { // Technically Today widgets can open urls, but supporting that would require @@ -181,11 +229,8 @@ - (void)handleOpenURLNotification:(NSNotification *)notification }]; } -RCT_EXPORT_METHOD(sendIntent - : (NSString *)action extras - : (NSArray *_Nullable)extras resolve - : (RCTPromiseResolveBlock)resolve reject - : (RCTPromiseRejectBlock)reject) +RCT_EXPORT_METHOD(sendIntent : (NSString *)action extras : (NSArray *_Nullable)extras resolve : (RCTPromiseResolveBlock) + resolve reject : (RCTPromiseRejectBlock)reject) { RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd)); } diff --git a/packages/react-native/React/Base/RCTUtils.h b/packages/react-native/React/Base/RCTUtils.h index a6b4ea0d0c02..6d77dd80bfdb 100644 --- a/packages/react-native/React/Base/RCTUtils.h +++ b/packages/react-native/React/Base/RCTUtils.h @@ -96,6 +96,9 @@ RCT_EXTERN UIApplication *__nullable RCTSharedApplication(void); // or view controller RCT_EXTERN UIWindow *__nullable RCTKeyWindow(void); +// Is this app a SceneDelegate app? +RCT_EXTERN BOOL RCTIsSceneDelegateApp(void); + // Returns the presented view controller, useful if you need // e.g. to present a modal view controller or alert over it RCT_EXTERN UIViewController *__nullable RCTPresentedViewController(void); diff --git a/packages/react-native/React/Base/RCTUtils.mm b/packages/react-native/React/Base/RCTUtils.mm index 82712cb3f9ec..15395bd57e8a 100644 --- a/packages/react-native/React/Base/RCTUtils.mm +++ b/packages/react-native/React/Base/RCTUtils.mm @@ -633,6 +633,24 @@ BOOL RCTRunningInAppExtension(void) return nil; } +BOOL RCTIsSceneDelegateApp(void) +{ + if (@available(iOS 13.0, *)) { + NSDictionary *sceneManifest = [[NSBundle mainBundle] infoDictionary][@"UIApplicationSceneManifest"]; + + if (sceneManifest) { + NSDictionary *sceneConfigurations = sceneManifest[@"UIApplicationSceneConfigurations"]; + if (sceneConfigurations && sceneConfigurations.count > 0) { + return YES; + } + } + + return NO; + } + + return NO; +} + UIStatusBarManager *__nullable RCTUIStatusBarManager(void) { return RCTKeyWindow().windowScene.statusBarManager; diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index e1efd2f73425..73721792589b 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -79,20 +79,32 @@ - (void)initialize _currentInterfaceDimensions = [self _exportedDimensions]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(interfaceOrientationDidChange) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) name:RCTUserInterfaceStyleDidChangeNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(interfaceFrameDidChange) - name:UIApplicationDidBecomeActiveNotification - object:nil]; + if (@available(iOS 13.0, *)) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(interfaceOrientationDidChange) + name:UISceneDidActivateNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(interfaceFrameDidChange) + name:UISceneDidActivateNotification + object:nil]; + } else { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(interfaceOrientationDidChange) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(interfaceFrameDidChange) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + } #if TARGET_OS_IOS @@ -138,10 +150,13 @@ - (void)_cleanupObservers name:RCTAccessibilityManagerDidUpdateMultiplierNotification object:[_moduleRegistry moduleForName:"AccessibilityManager"]]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + if (@available(iOS 13.0, *)) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UISceneDidActivateNotification object:nil]; + } else { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + } [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTUserInterfaceStyleDidChangeNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; [_applicationWindow removeObserver:self forKeyPath:kFrameKeyPath]; @@ -239,10 +254,10 @@ - (void)interfaceOrientationDidChange { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST UIApplication *application = RCTSharedApplication(); - UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation; + UIWindow *keyWindow = RCTKeyWindow(); + UIInterfaceOrientation nextOrientation = keyWindow.windowScene.interfaceOrientation; - BOOL isRunningInFullScreen = - CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds); + BOOL isRunningInFullScreen = CGRectEqualToRect(keyWindow.frame, keyWindow.screen.bounds); // We are catching here two situations for multitasking view: // a) The app is in Split View and the container gets resized -> !isRunningInFullScreen // b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen-> diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index dae3a107f6bb..277ce2699b12 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -60,6 +60,10 @@ target 'RNTester' do pods('RNTester') end +target 'RNTester (AppDelegate)' do + pods('RNTester (AppDelegate)') +end + target 'RNTesterUnitTests' do pods('RNTesterUnitTests') pod 'React-RCTTest', :path => "./RCTTest" diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index d059054edf45..74806755d520 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -497,6 +497,7 @@ PODS: - RCT-Folly/Fabric - RCTTypeSafety (= 1000.0.0) - React-Core/CoreModulesHeaders (= 1000.0.0) + - React-debug - React-jsi (= 1000.0.0) - React-jsinspector - React-jsinspectorcdp @@ -1246,6 +1247,7 @@ PODS: - React-FabricComponents/components/rncore (= 1000.0.0) - React-FabricComponents/components/safeareaview (= 1000.0.0) - React-FabricComponents/components/scrollview (= 1000.0.0) + - React-FabricComponents/components/switch (= 1000.0.0) - React-FabricComponents/components/text (= 1000.0.0) - React-FabricComponents/components/textinput (= 1000.0.0) - React-FabricComponents/components/unimplementedview (= 1000.0.0) @@ -1425,6 +1427,33 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga + - React-FabricComponents/components/switch (1000.0.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga - React-FabricComponents/components/text (1000.0.0): - boost - DoubleConversion @@ -1662,6 +1691,7 @@ PODS: - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing + - React-oscompat - React-perflogger (= 1000.0.0) - React-runtimeexecutor - SocketRocket @@ -1730,12 +1760,13 @@ PODS: - hermes-engine - RCT-Folly - RCT-Folly/Fabric - - React-cxxreact (= 1000.0.0) - - React-jsi (= 1000.0.0) + - React-cxxreact + - React-debug + - React-jsi - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - - React-perflogger (= 1000.0.0) + - React-perflogger - React-runtimeexecutor - SocketRocket - React-jsinspector (1000.0.0): @@ -1797,6 +1828,7 @@ PODS: - RCT-Folly - RCT-Folly/Fabric - React-cxxreact (= 1000.0.0) + - React-debug - React-jsi (= 1000.0.0) - React-jsinspector - React-jsinspectorcdp @@ -1850,6 +1882,7 @@ PODS: - React-callinvoker - React-Core - React-cxxreact + - React-debug - React-featureflags - React-jsi - React-jsinspector @@ -1874,6 +1907,7 @@ PODS: - fast_float - fmt - glog + - hermes-engine - RCT-Folly - RCT-Folly/Fabric - React-jsi @@ -1987,6 +2021,7 @@ PODS: - React-jsinspectorcdp - React-jsinspectornetwork - React-jsinspectortracing + - React-performancecdpmetrics - React-performancetimeline - React-RCTAnimation - React-RCTFBReactNativeSpec @@ -2073,6 +2108,7 @@ PODS: - RCT-Folly/Fabric - RCTTypeSafety - React-Core/RCTNetworkHeaders + - React-debug - React-featureflags - React-jsi - React-jsinspectorcdp @@ -2098,6 +2134,7 @@ PODS: - RCT-Folly - RCT-Folly/Fabric - React-Core + - React-debug - React-jsi - React-jsinspector - React-jsinspectorcdp @@ -2274,7 +2311,8 @@ PODS: - React-timing - React-utils - SocketRocket - - React-timing (1000.0.0) + - React-timing (1000.0.0): + - React-debug - React-utils (1000.0.0): - boost - DoubleConversion @@ -2673,84 +2711,84 @@ SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 - FBLazyVector: d3c2dd739a63c1a124e775df075dc7c517a719cb + FBLazyVector: 1387c5e43d2d6b093cec8efb2e25cc0fac8ef30b fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 - hermes-engine: 5a9adf9081befbac6b81bc0c81522430a7eb7da1 + hermes-engine: 013d35578e8c417727a1b441176629cfe051ad03 MyNativeView: 26b517931cc8bfc7b602c410572b323348185461 NativeCxxModuleExample: 6a9788a749d522f8b6cc55a56f4760a670e4e2eb OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf - RCTRequired: a00614e2da5344c2cda3d287050b6cee00e21dc6 - RCTTypeSafety: 459a16418c6b413060d35434ba3e83f5b0bd2651 - React: 170a01a19ba2525ab7f11243e2df6b19bf268093 - React-callinvoker: f08f425e4043cd1998a158b6e39a6aed1fd1d718 - React-Core: d35c5cf69898fd026e5cd93a0454b1d42e999d3e - React-CoreModules: 3ce1d43f6cc37f43759ec543ce1c0010080f1de1 - React-cxxreact: 52ea845cf7eb1e0fb201ed36e2192de6522a1f60 - React-debug: 195df38487d3f48a7af04deddeb4a5c6d4440416 - React-defaultsnativemodule: 8afea5a4bd07addb523bf48489b8a684ea1bdff0 - React-domnativemodule: 00a3d08568b4e573dcc21ecec829ed425ab10763 - React-Fabric: e2ee903224e68c8fa24aa96e217bad36d7660f5a - React-FabricComponents: 82043c131381c8b1f6e91c559eb04cdf61decdb7 - React-FabricImage: 264c9ce5241e43e25b94c8de55ac6c3c8a046472 - React-featureflags: 595651ea13c63a9f77f06d9a1973b665b4a28b7e - React-featureflagsnativemodule: 06823479a2ee210cfa0e9c19447c2722a8d995f2 - React-graphics: 1f99b9b5515eac389f0cf9c85b03abc366d6a933 - React-hermes: f1034a4d5d8edaf78d47a4f21e9898c4bf6fe02f - React-idlecallbacksnativemodule: 4e65f183318b8a0fbabc481a4eafc0f0d62d1cbf - React-ImageManager: a6833445e17879933378b7c0ba45ee42115c14bc - React-jserrorhandler: bec134a192c50338193544404d45df24fb8a19ca - React-jsi: 4ad77650fb0ca4229569eb2532db7a87e3d12662 - React-jsiexecutor: fa5b80bdbe1ceffc33a892da20fc07b4dfa4df7a - React-jsinspector: 10b5dc4eef2a3d05b80be2114ed676496c5bf59c - React-jsinspectorcdp: 5fb266e5f23d3a2819ba848e9d4d0b6b00f95934 - React-jsinspectornetwork: 1655a81f3fe14789df41e063bd56dd130cc3562a - React-jsinspectortracing: 5b0be488e06958a572e1badfe8509929ae1cc83b - React-jsitooling: 9e563b89f94cf4baf872fe47105d60ae83f4ce4d - React-jsitracing: ce443686f52538d1033ce7db1e7d643e866262f0 - React-logger: 116c3ae5a9906671d157aa00882a5ee75a5a7ebc - React-Mapbuffer: fc937cfa41140d7724c559c3d16c50dd725361c8 - React-microtasksnativemodule: 09899c7389250279bdcc5384f0281bb069979855 - React-NativeModulesApple: d05b718ccd8b68c184e76dbc1efb63385197595b - React-oscompat: 7133e0e945cda067ae36b22502df663d73002864 - React-perflogger: ada3cdf3dfc8b7cd1fabe3c91b672e23981611ab - React-performancecdpmetrics: 89ea4585d30c7681ab1378afb3fd845cd0647860 - React-performancetimeline: e7d5849d89ee39557dcd56dfb6e7b0d49003d925 - React-RCTActionSheet: 1bf8cc8086ad1c15da3407dfb7bc9dd94dc7595d - React-RCTAnimation: 263593e66c89bf810604b1ace15dfa382a1ca2df - React-RCTAppDelegate: f66939ac7ce5da6eb839c3d84a7098e62498a791 - React-RCTBlob: 7b76230c53fe87d305eeeb250b0aae031bb6cbae - React-RCTFabric: 2fd2ef899c7219fd39fd61c39750510f88a81434 - React-RCTFBReactNativeSpec: bd9c8093cc3388fe55a8cce47e66712e326e967a - React-RCTImage: 3e28f3015bc7e8375298e01ebb2032aa05635c32 - React-RCTLinking: 06742cfad41c506091403a414370743a4ed75af3 - React-RCTNetwork: b4577eec0092c16d8996e415e4cac7a372d6d362 - React-RCTPushNotification: ea11178d499696516e0ff9ae335edbe99b06f94b - React-RCTRuntime: 925039e78fc530e0421c308ccc607f214f3c7be1 - React-RCTSettings: d3c2dd305ec81f7faf42762ec598d57f07fd43be - React-RCTTest: 2db46eda60bc2228cb67622a580e8e86b00088d9 - React-RCTText: e416825b80c530647040ef91d23ffd35ccc87981 - React-RCTVibration: 1837a27fc16eeffc9509779c3334fde54c012bcc - React-rendererconsistency: 777c894edc43dde01499189917ac54ee76ae6a6a - React-renderercss: a9cb6ba7f49a80dc4b4f7008bae1590d12f27049 - React-rendererdebug: fea8bde927403a198742b2d940a5f1cd8230c0b4 - React-RuntimeApple: 6a0c164a8855edb4987b90da2d4d8601302de72d - React-RuntimeCore: 6dec37113b759b76641bd028bfbbbec8cf923356 - React-runtimeexecutor: f6ad01d321a3b99e772509b4d6f5c25b670103fa - React-RuntimeHermes: d4f661204d3061219a63951eb4efed4dcaf3f12f - React-runtimescheduler: ae44fe8b4170a9d59f62e8b7d7b060c179db739d - React-timing: 9d49179631e5e3c759e6e82d4c613c73da80a144 - React-utils: 0944df8d553d66b27f486282c42a84a969fd2f6c - ReactAppDependencyProvider: 68f2d2cefd6c9b9f2865246be2bfe86ebd49238d - ReactCodegen: ff8d79aa6b195efceb75a7cd3cafa9f05d1cbfe0 - ReactCommon: a53973ab35d399560ace331ec9e2b26db0592cec - ReactCommon-Samples: dcc128cbf51ac38d2578791750d0a046d1b8a5e9 + RCTRequired: 77f28efe20e4d2c37103bccc333c0d110a30c268 + RCTTypeSafety: 963c6342a1a6988047fc2406e8b2e3095664c38a + React: 10b377126ff8e3814efb895e44af233746203eae + React-callinvoker: 8c0374c37f7f62218d1a37bf9c61fde47248a2e0 + React-Core: 66085076495d7daf06195060799a072262efa0ee + React-CoreModules: 2c161c09de16582257c15e7499dd76ea8e2dc12e + React-cxxreact: 51bebc3c68f1c732fe558ea5c1c4f776593a71b3 + React-debug: bc3231e6b793d17d18a771daaaabd389f588c6e2 + React-defaultsnativemodule: 42b80c99218d4eb7d69d73530619181e351f0944 + React-domnativemodule: 5093c5b3124152a9f1f0328b9d83896a385cd217 + React-Fabric: 8836cc32d509b93685269c23cf8c7cf3e5f71ab6 + React-FabricComponents: f99fb74642ce488eb9da39048537d1b34d5618ae + React-FabricImage: 4cb9574379135cca5bde5d68130376d4b7cdd775 + React-featureflags: 063077b799ac971730ed265cbb806ae37fdbc0bd + React-featureflagsnativemodule: aa451bcc59344491adf8dfe1afe24588204c4e4d + React-graphics: 09d687f4119f7ba6aa0d88a8a4ef7d677a9eeb4d + React-hermes: 1f8b853dbb2276e428e3a9442f50e7ad3ad0f656 + React-idlecallbacksnativemodule: f08b6e346c34ecc3b58b2c92604e4e750ef0bdbe + React-ImageManager: e752a44bc932a911f2641aa93074f3624cc06229 + React-jserrorhandler: 8f01fff0fc79a7ef682cf898764026b09b128360 + React-jsi: 828e75837067957a7229a9079806025c46e116f4 + React-jsiexecutor: b605ba028fc3a4e86c36ea2c59fac46ee25d04b6 + React-jsinspector: bdca03ccfe08a14b2fcaae6feb676df40bdd932e + React-jsinspectorcdp: 2fe3be3d89c2b005b2701606f33e0d2b44e0cf94 + React-jsinspectornetwork: c1b2537801416a72921d757f5c5c8895ff76541c + React-jsinspectortracing: 03a167475232364d26c2d765574fda8b1e0ecb14 + React-jsitooling: 1248a48cdd0da8577c7d8accc4c9e18dda2005e2 + React-jsitracing: cc8f3b2ad427357cbb9f512213f82d61bca85204 + React-logger: 2609fa3e4aa50ddcd34e1f7223dc0b9de8a8f1fc + React-Mapbuffer: 3a52bd35cad2b6e2b48a88da6fc61ee8096beded + React-microtasksnativemodule: dc91e479133dfff3e2c8f929ed5e0b4f48818754 + React-NativeModulesApple: 51186952811e19870d5942cd39f35e269f89761c + React-oscompat: b7e977877a716e520f0488cbdb0d5a1e209fb55e + React-perflogger: 889e1b94c66fb71984f5d014c50aaf10153e711c + React-performancecdpmetrics: 912b773aae7ca0a038c05a0d42b5d3a2bc906c5b + React-performancetimeline: 82e543de5d781de398b092b430ef12d05d39699b + React-RCTActionSheet: d0d1b20b35b1cdc5d11e3e0881b5895eb43eee42 + React-RCTAnimation: 2a7e9ac6cec544b34b636b23157b0ce1f167a841 + React-RCTAppDelegate: 058efed0e0b6290cf3bae12b2232cc60df885a2e + React-RCTBlob: 0220f5e83bf9bc92497223f9b43f476190de925e + React-RCTFabric: e22f35ba4a009b1e59256aebec2a57ebc1bda645 + React-RCTFBReactNativeSpec: 1b72d3a0a3bbdf671f01d47d2b07b580824fc6f6 + React-RCTImage: a71fd42b19ce4bab5be8370dfd93b60392ff1d84 + React-RCTLinking: 9f785f55e0ef7bea7029d57e93c4d2b196a0841d + React-RCTNetwork: 17926a4b47c591140e899146cbd0ce2fab23babf + React-RCTPushNotification: ccfe7cf75b4ac2d7a0139b274494f61366accfb2 + React-RCTRuntime: 7b851596bdaa140fbca41846f693a9f85d390878 + React-RCTSettings: d97acdbe2fb3829e96ae9453b9f4474ee4fbeb9b + React-RCTTest: 6eb6c600c810db52c3ef008ce28fb7abea7631d2 + React-RCTText: 4759b7427d5c98c17c1370b6a0746f9fa17932ec + React-RCTVibration: 18415fae9bd3c5a3b4ae2a3d0a096a16f3314594 + React-rendererconsistency: 0fe0a1d87d327738ec149d69d4dec4af42b61409 + React-renderercss: 8e80a281cd06aa52dd07c3df0e68b8708cbeca2a + React-rendererdebug: a4d5be536ac3672f922b1c6ce8da3aaead9a4efc + React-RuntimeApple: d83ef323a5f5b9d0454fc1377a9d287e9036b606 + React-RuntimeCore: 7c3382e041077c280e5b4efd481b1551057b16c0 + React-runtimeexecutor: 50aabe05827e11bac939b41065b52d41efac0db9 + React-RuntimeHermes: 784e63a0d4de27f4b6b1d3e7894edd6467dc309b + React-runtimescheduler: cc89da6b3b3c1e13fcc56351edad4eb3dd4aacf1 + React-timing: cdd0354b497ba5241973cbc64d6aa25ecc66aaa8 + React-utils: 01cba75aa61ea3a9b15fc3b2c7e03847505f790e + ReactAppDependencyProvider: f4c5c081b75cc7506854adf9c293bbb1902b434e + ReactCodegen: 5a2d9dbe44f2b16e06cbe68d2215d71776ae5c8b + ReactCommon: e955e436f41c7816dd74f5152a8f4d3a3d24b6f0 + ReactCommon-Samples: fe5e9d4aa17dda687a78d8fbb612468b9bb45575 ScreenshotManager: 370045f403c555760ae26d85a01dda89d257fa7b SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: 59290f2ce3fc5c34797a21244288cad99b357b63 + Yoga: fa211e60174f5ca5c8d58f830f9da3abf66878b7 -PODFILE CHECKSUM: 995beda3236c2c76801e7a4efc7fedcd390220e6 +PODFILE CHECKSUM: 21be30d7d0e6382a4c9d45a5e70359e583b73403 COCOAPODS: 1.16.2 diff --git a/packages/rn-tester/RNTester/AppDelegate.h b/packages/rn-tester/RNTester/AppDelegate.h index df578639dc44..1fb7f1895aec 100644 --- a/packages/rn-tester/RNTester/AppDelegate.h +++ b/packages/rn-tester/RNTester/AppDelegate.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#if RNTESTER_USE_APPDELEGATE + #import #import #import @@ -15,3 +17,13 @@ @property (nonatomic, strong, nonnull) RCTReactNativeFactory *reactNativeFactory; @end + +#else + +#import + +@interface AppDelegate : UIResponder + +@end + +#endif diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index cf02164f8945..a896bfbc052b 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -7,6 +7,7 @@ #import "AppDelegate.h" +#if RNTESTER_USE_APPDELEGATE #import #import @@ -162,3 +163,8 @@ - (NSURL *)bundleURL } @end +#else +@implementation AppDelegate + +@end +#endif diff --git a/packages/rn-tester/RNTester/SceneDelegate.h b/packages/rn-tester/RNTester/SceneDelegate.h new file mode 100644 index 000000000000..db3a13a9634e --- /dev/null +++ b/packages/rn-tester/RNTester/SceneDelegate.h @@ -0,0 +1,27 @@ +/* + * 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 +#import +#import + +@class ReactNativeDelegate; +@class RCTReactNativeFactory; + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) ReactNativeDelegate *reactNativeDelegate; +@property (strong, nonatomic) RCTReactNativeFactory *reactNativeFactory; + +- (NSDictionary *)prepareInitialProps; + +@end + +@interface ReactNativeDelegate : RCTDefaultReactNativeFactoryDelegate + +@end diff --git a/packages/rn-tester/RNTester/SceneDelegate.mm b/packages/rn-tester/RNTester/SceneDelegate.mm new file mode 100644 index 000000000000..a6391ba50f3d --- /dev/null +++ b/packages/rn-tester/RNTester/SceneDelegate.mm @@ -0,0 +1,102 @@ +/* + * 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 "SceneDelegate.h" + +#import + +#import +#import +#import +#import +#import + +#import + +#import +#ifndef RN_DISABLE_OSS_PLUGIN_HEADER +#import +#endif + +#if __has_include() +#define USE_OSS_CODEGEN 1 +#import +#else +#define USE_OSS_CODEGEN 0 +#endif + +@interface SceneDelegate () +@end + +@implementation SceneDelegate + +- (NSDictionary *)prepareInitialProps +{ + NSMutableDictionary *initProps = [NSMutableDictionary dictionary]; + NSString *routeUri = [[NSUserDefaults standardUserDefaults] stringForKey:@"route"]; + if (routeUri) { + NSString *example = [NSString stringWithFormat:@"rntester://example/%@Example", routeUri]; + initProps[@"exampleFromAppetizeParams"] = example; + } + return [initProps copy]; +} + +- (void)scene:(UIScene *)scene + willConnectToSession:(UISceneSession *)session + options:(UISceneConnectionOptions *)connectionOptions +{ + if (![scene isKindOfClass:[UIWindowScene class]]) + return; + + UIWindowScene *windowScene = (UIWindowScene *)scene; + self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; + + ReactNativeDelegate *delegate = [[ReactNativeDelegate alloc] init]; + RCTReactNativeFactory *factory = [[RCTReactNativeFactory alloc] initWithDelegate:delegate]; + +#if USE_OSS_CODEGEN + delegate.dependencyProvider = [[RCTAppDependencyProvider alloc] init]; +#endif + + self.reactNativeDelegate = delegate; + self.reactNativeFactory = factory; + + [factory startReactNativeWithModuleName:@"RNTesterApp" + inWindow:self.window + initialProperties:[self prepareInitialProps] + connectionOptions:connectionOptions]; +} + +- (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts +{ + [RCTLinkingManager scene:scene openURLContexts:URLContexts]; +} + +- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity +{ + [RCTLinkingManager scene:scene continueUserActivity:userActivity]; +} + +@end + +@implementation ReactNativeDelegate + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self bundleURL]; +} + +- (NSURL *)bundleURL +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"js/RNTesterApp.ios"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +@end diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 4ceae9d500a1..678915626cc2 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -14,12 +14,24 @@ 383889DA23A7398900D06C3E /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */; }; 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; + 79B29C0F2E607763007612A5 /* UpdatePropertiesExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */; }; + 79B29C102E607763007612A5 /* FlexibleSizeExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */; }; + 79B29C112E607763007612A5 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; }; + 79B29C132E607763007612A5 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; + 79B29C142E607763007612A5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 79B29C182E607763007612A5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; }; + 79B29C192E607763007612A5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; + 79B29C1A2E607763007612A5 /* RNTesterBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0EA618022BE537D3001875EF /* RNTesterBundle.bundle */; }; + 79B29C1B2E607763007612A5 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */; }; + 79B29C1C2E607763007612A5 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; + 79B29C2E2E607A99007612A5 /* SceneDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 79B29C2D2E607A99007612A5 /* SceneDelegate.mm */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; 832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; }; A36E4394472D388C2F6BBABA /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 48A747D61749335D863001E9 /* libPods-RNTester.a */; }; A975CA6C2C05EADF0043F72A /* RCTNetworkTaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */; }; BF2C34488C1E5FF62D331DD4 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */; }; CD10C7A5290BD4EB0033E1ED /* RCTEventEmitterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */; }; + D0EB6B72078F25C405242A39 /* libPods-RNTester (AppDelegate).a in Frameworks */ = {isa = PBXBuildFile; fileRef = 309656AE6EF12137FEBD20CF /* libPods-RNTester (AppDelegate).a */; }; E62F11832A5C6580000BF1C8 /* FlexibleSizeExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */; }; E62F11842A5C6584000BF1C8 /* UpdatePropertiesExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */; }; E7C1241A22BEC44B00DA25C0 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */; }; @@ -59,6 +71,7 @@ E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB213022B2C649005AC45F /* JavaScriptCore.framework */; }; E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB218B22B41FCD005AC45F /* XCTest.framework */; }; F0D621C32BBB9E38005960AC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */; }; + F0DD918861EC4E65E79F68AF /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 48A747D61749335D863001E9 /* libPods-RNTester.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -79,28 +92,34 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0D075D0DFD23608C4802DA5A /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; 0EA618022BE537D3001875EF /* RNTesterBundle.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = RNTesterBundle.bundle; path = RNTester/RNTesterBundle.bundle; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* RNTester.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RNTester.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = ""; }; + 23A9B2A7771CB44447C7EB4B /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = ""; }; 272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = ""; }; 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UpdatePropertiesExampleView.mm; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm; sourceTree = ""; }; - 2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = ""; }; 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FlexibleSizeExampleView.mm; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.mm; sourceTree = ""; }; 27F441EA1BEBE5030039B79C /* FlexibleSizeExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlexibleSizeExampleView.h; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.h; sourceTree = ""; }; 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; + 309656AE6EF12137FEBD20CF /* libPods-RNTester (AppDelegate).a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester (AppDelegate).a"; sourceTree = BUILT_PRODUCTS_DIR; }; 359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = ""; }; 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = ""; }; 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = ""; }; 48A747D61749335D863001E9 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BF5B4B428E8613E16EC8289 /* Pods-RNTester (AppDelegate).release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester (AppDelegate).release.xcconfig"; path = "Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate).release.xcconfig"; sourceTree = ""; }; 5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = ""; }; 66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = ""; }; + 79A734792E607E17009A7E41 /* Info-AppDelegate.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-AppDelegate.plist"; path = "RNTester/Info-AppDelegate.plist"; sourceTree = ""; }; + 79B29C242E607763007612A5 /* RNTester (AppDelegate).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RNTester (AppDelegate).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 79B29C2C2E607A99007612A5 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SceneDelegate.h; path = RNTester/SceneDelegate.h; sourceTree = ""; }; + 79B29C2D2E607A99007612A5 /* SceneDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = SceneDelegate.mm; path = RNTester/SceneDelegate.mm; sourceTree = ""; }; 7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = ""; }; 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = ""; }; 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = ""; }; 8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = ""; }; - 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkTaskTests.m; sourceTree = ""; }; AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = ""; }; CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventEmitterTests.m; sourceTree = ""; }; @@ -166,6 +185,7 @@ E7DB215E22B2F3EC005AC45F /* RCTLoggingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLoggingTests.m; sourceTree = ""; }; E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = ""; }; E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; }; + E87E6CCCE19B43DD1B25C37A /* Pods-RNTester (AppDelegate).debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester (AppDelegate).debug.xcconfig"; path = "Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate).debug.xcconfig"; sourceTree = ""; }; E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; /* End PBXFileReference section */ @@ -176,6 +196,15 @@ buildActionMask = 2147483647; files = ( A36E4394472D388C2F6BBABA /* libPods-RNTester.a in Frameworks */, + F0DD918861EC4E65E79F68AF /* libPods-RNTester.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B29C152E607763007612A5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D0EB6B72078F25C405242A39 /* libPods-RNTester (AppDelegate).a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -216,8 +245,11 @@ F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */, AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */, E771AEEA22B44E3100EA1189 /* Info.plist */, + 79A734792E607E17009A7E41 /* Info-AppDelegate.plist */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 5C60EB1B226440DB0018C04F /* AppDelegate.mm */, + 79B29C2C2E607A99007612A5 /* SceneDelegate.h */, + 79B29C2D2E607A99007612A5 /* SceneDelegate.mm */, 13B07FB71A68108700A75B9A /* main.m */, 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */, 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */, @@ -268,6 +300,7 @@ 48A747D61749335D863001E9 /* libPods-RNTester.a */, DF9F45393190A3F008764D08 /* libPods-RNTesterIntegrationTests.a */, E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */, + 309656AE6EF12137FEBD20CF /* libPods-RNTester (AppDelegate).a */, ); name = Frameworks; sourceTree = ""; @@ -301,6 +334,7 @@ 13B07F961A680F5B00A75B9A /* RNTester.app */, E7DB209F22B2BA84005AC45F /* RNTesterUnitTests.xctest */, E7DB215322B2F332005AC45F /* RNTesterIntegrationTests.xctest */, + 79B29C242E607763007612A5 /* RNTester (AppDelegate).app */, ); name = Products; sourceTree = ""; @@ -308,12 +342,14 @@ E23BD6487B06BD71F1A86914 /* Pods */ = { isa = PBXGroup; children = ( - 2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */, - 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */, 66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */, 7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */, 359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */, 8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */, + 23A9B2A7771CB44447C7EB4B /* Pods-RNTester.debug.xcconfig */, + 0D075D0DFD23608C4802DA5A /* Pods-RNTester.release.xcconfig */, + E87E6CCCE19B43DD1B25C37A /* Pods-RNTester (AppDelegate).debug.xcconfig */, + 4BF5B4B428E8613E16EC8289 /* Pods-RNTester (AppDelegate).release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -396,6 +432,28 @@ productReference = 13B07F961A680F5B00A75B9A /* RNTester.app */; productType = "com.apple.product-type.application"; }; + 79B29C0C2E607763007612A5 /* RNTester (AppDelegate) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79B29C212E607763007612A5 /* Build configuration list for PBXNativeTarget "RNTester (AppDelegate)" */; + buildPhases = ( + 6D3C9EEA475B421079CE80D2 /* [CP] Check Pods Manifest.lock */, + 79B29C0E2E607763007612A5 /* Sources */, + 79B29C152E607763007612A5 /* Frameworks */, + 79B29C172E607763007612A5 /* Resources */, + 79B29C1D2E607763007612A5 /* Build JS Bundle */, + 79B29C1E2E607763007612A5 /* [RN] Copy Hermes Framework */, + BAFDB2A2B088CE73333153E5 /* [CP] Embed Pods Frameworks */, + CE382DBF5D976ADF8308AD2D /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "RNTester (AppDelegate)"; + productName = "Hello World"; + productReference = 79B29C242E607763007612A5 /* RNTester (AppDelegate).app */; + productType = "com.apple.product-type.application"; + }; E7DB209E22B2BA84005AC45F /* RNTesterUnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = E7DB20A622B2BA84005AC45F /* Build configuration list for PBXNativeTarget "RNTesterUnitTests" */; @@ -473,6 +531,7 @@ projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* RNTester */, + 79B29C0C2E607763007612A5 /* RNTester (AppDelegate) */, E7DB209E22B2BA84005AC45F /* RNTesterUnitTests */, E7DB215222B2F332005AC45F /* RNTesterIntegrationTests */, ); @@ -492,6 +551,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79B29C172E607763007612A5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79B29C182E607763007612A5 /* Images.xcassets in Resources */, + 79B29C192E607763007612A5 /* LaunchScreen.storyboard in Resources */, + 79B29C1A2E607763007612A5 /* RNTesterBundle.bundle in Resources */, + 79B29C1B2E607763007612A5 /* PrivacyInfo.xcprivacy in Resources */, + 79B29C1C2E607763007612A5 /* legacy_image@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E7DB209D22B2BA84005AC45F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -616,6 +687,62 @@ shellPath = /bin/sh; shellScript = "set -e\n\nexport PROJECT_ROOT=\"$SRCROOT\"\nexport ENTRY_FILE=\"$SRCROOT/js/RNTesterApp.ios.js\"\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true \n\nWITH_ENVIRONMENT=\"../react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; + 6D3C9EEA475B421079CE80D2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RNTester (AppDelegate)-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 79B29C1D2E607763007612A5 /* Build JS Bundle */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Build JS Bundle"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nexport PROJECT_ROOT=\"$SRCROOT\"\nexport ENTRY_FILE=\"$SRCROOT/js/RNTesterApp.ios.js\"\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true \n\nWITH_ENVIRONMENT=\"../react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 79B29C1E2E607763007612A5 /* [RN] Copy Hermes Framework */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "[RN] Copy Hermes Framework"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". ../react-native/sdks/hermes-engine/utils/copy-hermes-xcode.sh\n"; + }; 79E8BE2B119D4C5CCD2F04B3 /* [RN] Copy Hermes Framework */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -695,6 +822,40 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + BAFDB2A2B088CE73333153E5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + CE382DBF5D976ADF8308AD2D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester (AppDelegate)/Pods-RNTester (AppDelegate)-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; E446637427ECD101CAACE52B /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -720,6 +881,7 @@ buildActionMask = 2147483647; files = ( E62F11842A5C6584000BF1C8 /* UpdatePropertiesExampleView.mm in Sources */, + 79B29C2E2E607A99007612A5 /* SceneDelegate.mm in Sources */, E62F11832A5C6580000BF1C8 /* FlexibleSizeExampleView.mm in Sources */, 832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */, 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */, @@ -727,6 +889,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79B29C0E2E607763007612A5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79B29C0F2E607763007612A5 /* UpdatePropertiesExampleView.mm in Sources */, + 79B29C102E607763007612A5 /* FlexibleSizeExampleView.mm in Sources */, + 79B29C112E607763007612A5 /* SwiftTest.swift in Sources */, + 79B29C132E607763007612A5 /* AppDelegate.mm in Sources */, + 79B29C142E607763007612A5 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E7DB209B22B2BA84005AC45F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -794,7 +968,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */; + baseConfigurationReference = 23A9B2A7771CB44447C7EB4B /* Pods-RNTester.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -832,7 +1006,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */; + baseConfigurationReference = 0D075D0DFD23608C4802DA5A /* Pods-RNTester.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -867,6 +1041,91 @@ }; name = Release; }; + 79B29C222E607763007612A5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E87E6CCCE19B43DD1B25C37A /* Pods-RNTester (AppDelegate).debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "RNTESTER_USE_APPDELEGATE=1", + ); + HEADER_SEARCH_PATHS = ( + "${PODS_ROOT}/Headers/Private/Yoga", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info-AppDelegate.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + ); + "LIBRARY_SEARCH_PATHS[arch=*]" = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-framework", + "\"JavaScriptCore\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.meta.RNTester.localDevelopment; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 79B29C232E607763007612A5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4BF5B4B428E8613E16EC8289 /* Pods-RNTester (AppDelegate).release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; + EXCLUDED_ARCHS = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "RNTESTER_USE_APPDELEGATE=1", + ); + HEADER_SEARCH_PATHS = ( + "${PODS_ROOT}/Headers/Private/Yoga", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info-AppDelegate.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-framework", + "\"JavaScriptCore\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.meta.RNTester.localDevelopment; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1223,6 +1482,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 79B29C212E607763007612A5 /* Build configuration list for PBXNativeTarget "RNTester (AppDelegate)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79B29C222E607763007612A5 /* Debug */, + 79B29C232E607763007612A5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RNTesterPods" */ = { isa = XCConfigurationList; buildConfigurations = ( From 8b4adc01740e39240994f58cfc697f4b0d5aa921 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 08:31:54 +0200 Subject: [PATCH 2/6] feat: provide two configurations for launching RNTester based on SceneDelegate and AppDelegate --- .../rn-tester/RNTester/Info-AppDelegate.plist | 67 +++++++++++++++++++ packages/rn-tester/RNTester/Info.plist | 17 +++++ 2 files changed, 84 insertions(+) create mode 100644 packages/rn-tester/RNTester/Info-AppDelegate.plist diff --git a/packages/rn-tester/RNTester/Info-AppDelegate.plist b/packages/rn-tester/RNTester/Info-AppDelegate.plist new file mode 100644 index 000000000000..373b8322fdc7 --- /dev/null +++ b/packages/rn-tester/RNTester/Info-AppDelegate.plist @@ -0,0 +1,67 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + com.reactjs.ios + CFBundleURLSchemes + + rntester + + + + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! + NSPhotoLibraryUsageDescription + You need to add NSPhotoLibraryUsageDescription key in Info.plist to enable photo library usage, otherwise it is going to *fail silently*! + RCTNewArchEnabled + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 373b8322fdc7..3004824d996f 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -61,6 +61,23 @@ UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneDelegateClassName + SceneDelegate + UISceneConfigurationName + Default Configuration + + + + UIViewControllerBasedStatusBarAppearance From 2863c4c00469e9b81157fb002785b113917c66ac Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 08:32:25 +0200 Subject: [PATCH 3/6] feat: migrate RNTester NativeExampleViews to support SceneDelegate --- .../FlexibleSizeExampleView.mm | 9 +++- .../UpdatePropertiesExampleView.mm | 9 +++- .../ios/HelloWorld/AppDelegate.swift | 46 +----------------- private/helloworld/ios/SceneDelegate.swift | 47 +++++++++++++++++++ 4 files changed, 64 insertions(+), 47 deletions(-) create mode 100644 private/helloworld/ios/SceneDelegate.swift diff --git a/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm b/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm index d08dd63be1f0..a78b8b3419d4 100644 --- a/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm +++ b/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm @@ -13,6 +13,7 @@ #import #import "AppDelegate.h" +#import "SceneDelegate.h" @interface FlexibleSizeExampleViewManager : RCTViewManager @@ -44,9 +45,15 @@ - (instancetype)initWithFrame:(CGRect)frame if ((self = [super initWithFrame:frame])) { _sizeUpdated = NO; +#if RNTESTER_USE_APPDELEGATE AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + RCTReactNativeFactory* reactNativeFactory = appDelegate.reactNativeFactory; +#else + SceneDelegate *sceneDelegate = (SceneDelegate*)self.window.windowScene.delegate; + RCTReactNativeFactory* reactNativeFactory = sceneDelegate.reactNativeFactory; +#endif - _resizableRootView = (RCTRootView *)[appDelegate.reactNativeFactory.rootViewFactory + _resizableRootView = (RCTRootView *)[reactNativeFactory.rootViewFactory viewWithModuleName:@"RootViewSizeFlexibilityExampleApp"]; [_resizableRootView setSizeFlexibility:RCTRootViewSizeFlexibilityHeight]; diff --git a/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm b/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm index 6cf4a1a03f19..c83f6c6be47f 100644 --- a/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm +++ b/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm @@ -11,6 +11,7 @@ #import #import "AppDelegate.h" +#import "SceneDelegate.h" @interface UpdatePropertiesExampleViewManager : RCTViewManager @@ -39,10 +40,16 @@ - (instancetype)initWithFrame:(CGRect)frame if (self) { _beige = YES; +#if RNTESTER_USE_APPDELEGATE AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + RCTReactNativeFactory* reactNativeFactory = appDelegate.reactNativeFactory; +#else + SceneDelegate *sceneDelegate = (SceneDelegate*)self.window.windowScene.delegate; + RCTReactNativeFactory* reactNativeFactory = sceneDelegate.reactNativeFactory; +#endif _rootView = - (RCTRootView *)[appDelegate.reactNativeFactory.rootViewFactory viewWithModuleName:@"SetPropertiesExampleApp" + (RCTRootView *)[reactNativeFactory.rootViewFactory viewWithModuleName:@"SetPropertiesExampleApp" initialProperties:@{@"color" : @"beige"}]; _button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; diff --git a/private/helloworld/ios/HelloWorld/AppDelegate.swift b/private/helloworld/ios/HelloWorld/AppDelegate.swift index 0c86f2f469fe..196b917fd66f 100644 --- a/private/helloworld/ios/HelloWorld/AppDelegate.swift +++ b/private/helloworld/ios/HelloWorld/AppDelegate.swift @@ -5,51 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import React -import ReactAppDependencyProvider -import React_RCTAppDelegate import UIKit @main -class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - - var reactNativeDelegate: ReactNativeDelegate? - var reactNativeFactory: RCTReactNativeFactory? - - func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil - ) -> Bool { - let delegate = ReactNativeDelegate() - let factory = RCTReactNativeFactory(delegate: delegate) - delegate.dependencyProvider = RCTAppDependencyProvider() - - reactNativeDelegate = delegate - reactNativeFactory = factory - - window = UIWindow(frame: UIScreen.main.bounds) - - factory.startReactNative( - withModuleName: "HelloWorld", - in: window, - launchOptions: launchOptions - ) - - return true - } -} - -class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { - override func sourceURL(for bridge: RCTBridge) -> URL? { - self.bundleURL() - } - - override func bundleURL() -> URL? { - #if DEBUG - RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") - #else - Bundle.main.url(forResource: "main", withExtension: "jsbundle") - #endif - } -} +class AppDelegate: UIResponder, UIApplicationDelegate {} diff --git a/private/helloworld/ios/SceneDelegate.swift b/private/helloworld/ios/SceneDelegate.swift new file mode 100644 index 000000000000..ad805db941dd --- /dev/null +++ b/private/helloworld/ios/SceneDelegate.swift @@ -0,0 +1,47 @@ +/* + * 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 React +import React_RCTAppDelegate +import ReactAppDependencyProvider +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? + var reactNativeDelegate: ReactNativeDelegate? + var reactNativeFactory: RCTReactNativeFactory? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(windowScene: windowScene) + let delegate = ReactNativeDelegate() + let factory = RCTReactNativeFactory(delegate: delegate) + delegate.dependencyProvider = RCTAppDependencyProvider() + + reactNativeDelegate = delegate + reactNativeFactory = factory + + factory.startReactNative( + withModuleName: "HelloWorld", + in: window + ) + } +} + +class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { + override func sourceURL(for bridge: RCTBridge) -> URL? { + self.bundleURL() + } + + override func bundleURL() -> URL? { +#if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") +#else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") +#endif + } +} From 44d5a19ae720006f99eab04bd3d9fc2e349db653 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 12:19:22 +0200 Subject: [PATCH 4/6] fix: error in error handling in SnapshotExample --- packages/rn-tester/js/examples/Snapshot/SnapshotExample.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rn-tester/js/examples/Snapshot/SnapshotExample.js b/packages/rn-tester/js/examples/Snapshot/SnapshotExample.js index 85660887a680..81633e3d0278 100644 --- a/packages/rn-tester/js/examples/Snapshot/SnapshotExample.js +++ b/packages/rn-tester/js/examples/Snapshot/SnapshotExample.js @@ -45,7 +45,7 @@ class ScreenshotExample extends React.Component<{...}, $FlowFixMe> { takeScreenshot = () => { ScreenshotManager.takeScreenshot('window', {format: 'jpeg', quality: 0.8}) // See UIManager.js for options .then(uri => this.setState({uri})) - .catch(error => Alert.alert(error)); + .catch(error => Alert.alert(error.toString())); }; } From e9622201126f0a38718ed299cb79df77b806ee96 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 12:19:50 +0200 Subject: [PATCH 5/6] feat: enable multiple scenes capability in RNTester --- packages/rn-tester/RNTester/Info.plist | 2 +- .../ios/HelloWorld.xcodeproj/project.pbxproj | 20 +++++++++++-------- private/helloworld/ios/HelloWorld/Info.plist | 17 ++++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 3004824d996f..1da4ed05a235 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -64,7 +64,7 @@ UIApplicationSceneManifest UIApplicationSupportsMultipleScenes - + UISceneConfigurations UIWindowSceneSessionRoleApplication diff --git a/private/helloworld/ios/HelloWorld.xcodeproj/project.pbxproj b/private/helloworld/ios/HelloWorld.xcodeproj/project.pbxproj index dca49419fb7c..803bd6575fe7 100644 --- a/private/helloworld/ios/HelloWorld.xcodeproj/project.pbxproj +++ b/private/helloworld/ios/HelloWorld.xcodeproj/project.pbxproj @@ -10,10 +10,11 @@ 00E356F31AD99517003FC87E /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 6EA01F72FAC10D00AECACF94 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0EC7AB76F90EED035707BA4E /* PrivacyInfo.xcprivacy */; }; + 76084D952D70BAB500F9F58B /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76084D942D70BAB300F9F58B /* SceneDelegate.swift */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + B2FFEEE00299A4349E247472 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E325722B44AC0B20199E52A /* libPods-HelloWorld-HelloWorldTests.a */; }; + BB013549A1AADD4153F18D27 /* libPods-HelloWorld.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F459DE36E22401131A7C2D26 /* libPods-HelloWorld.a */; }; CDA0ED1A2D0B2D810079F561 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA0ED192D0B2D810079F561 /* AppDelegate.swift */; }; - D462E9F4436EDF91C8A1FA0A /* Pods_HelloWorld.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3F2101C8317E5C933C1BD4C /* Pods_HelloWorld.framework */; }; - D693EA25CB545D6C1C7F8538 /* Pods_HelloWorld_HelloWorldTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A97924660E462ECF2425C3A /* Pods_HelloWorld_HelloWorldTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -38,12 +39,13 @@ 3B4392A12AC88292D35C810B /* Pods-HelloWorld.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.debug.xcconfig"; sourceTree = ""; }; 5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = ""; }; 5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; sourceTree = ""; }; - 7A97924660E462ECF2425C3A /* Pods_HelloWorld_HelloWorldTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HelloWorld_HelloWorldTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 76084D942D70BAB300F9F58B /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = HelloWorld/LaunchScreen.storyboard; sourceTree = ""; }; 89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.release.xcconfig"; sourceTree = ""; }; - B3F2101C8317E5C933C1BD4C /* Pods_HelloWorld.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HelloWorld.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8E325722B44AC0B20199E52A /* libPods-HelloWorld-HelloWorldTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld-HelloWorldTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; CDA0ED192D0B2D810079F561 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = HelloWorld/AppDelegate.swift; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + F459DE36E22401131A7C2D26 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -51,7 +53,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D693EA25CB545D6C1C7F8538 /* Pods_HelloWorld_HelloWorldTests.framework in Frameworks */, + B2FFEEE00299A4349E247472 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,7 +61,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D462E9F4436EDF91C8A1FA0A /* Pods_HelloWorld.framework in Frameworks */, + BB013549A1AADD4153F18D27 /* libPods-HelloWorld.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -86,6 +88,7 @@ 13B07FAE1A68108700A75B9A /* HelloWorld */ = { isa = PBXGroup; children = ( + 76084D942D70BAB300F9F58B /* SceneDelegate.swift */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, @@ -100,8 +103,8 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - B3F2101C8317E5C933C1BD4C /* Pods_HelloWorld.framework */, - 7A97924660E462ECF2425C3A /* Pods_HelloWorld_HelloWorldTests.framework */, + F459DE36E22401131A7C2D26 /* libPods-HelloWorld.a */, + 8E325722B44AC0B20199E52A /* libPods-HelloWorld-HelloWorldTests.a */, ); name = Frameworks; sourceTree = ""; @@ -395,6 +398,7 @@ buildActionMask = 2147483647; files = ( CDA0ED1A2D0B2D810079F561 /* AppDelegate.swift in Sources */, + 76084D952D70BAB500F9F58B /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/private/helloworld/ios/HelloWorld/Info.plist b/private/helloworld/ios/HelloWorld/Info.plist index 07b050898d9d..6d2d2988e32f 100644 --- a/private/helloworld/ios/HelloWorld/Info.plist +++ b/private/helloworld/ios/HelloWorld/Info.plist @@ -46,6 +46,23 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneConfigurationName + Default Configuration + + + + UIViewControllerBasedStatusBarAppearance From 0ea401ee4bd885f50570761382d4b6283be764b7 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Wed, 10 Sep 2025 14:45:35 +0200 Subject: [PATCH 6/6] feat: migrate RN internal modules to SceneDelegate --- .../Libraries/AppDelegate/RCTAppSetupUtils.h | 5 +- .../Libraries/AppDelegate/RCTAppSetupUtils.mm | 9 +- .../AppDelegate/RCTReactNativeFactory.mm | 16 +-- .../AppDelegate/RCTRootViewFactory.mm | 8 +- .../Libraries/LinkingIOS/RCTLinkingManager.mm | 21 +-- .../react-native/React/Base/RCTBridgeModule.h | 63 +++++++-- .../React/Base/RCTMultiWindowUtils.h | 64 +++++++++ .../React/Base/RCTMultiWindowUtils.m | 39 ++++++ .../React/CoreModules/RCTAlertController.h | 2 + .../React/CoreModules/RCTAlertController.mm | 25 +++- .../React/CoreModules/RCTAlertManager.mm | 4 +- .../React/CoreModules/RCTAppearance.mm | 2 +- .../React/CoreModules/RCTDeviceInfo.mm | 29 ++-- .../ios/ReactCommon/RCTTurboModuleManager.h | 6 +- .../ios/ReactCommon/RCTTurboModuleManager.mm | 17 ++- .../platform/ios/ReactCommon/RCTHost.h | 2 + .../platform/ios/ReactCommon/RCTHost.mm | 5 + .../platform/ios/ReactCommon/RCTInstance.mm | 3 +- .../NativeModuleExample/Screenshot.mm | 11 +- packages/rn-tester/Podfile.lock | 132 +++++++++--------- 20 files changed, 324 insertions(+), 139 deletions(-) create mode 100644 packages/react-native/React/Base/RCTMultiWindowUtils.h create mode 100644 packages/react-native/React/Base/RCTMultiWindowUtils.m diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h index 5fb3af23b4aa..9fc6b7fb0fef 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h @@ -29,9 +29,8 @@ class RuntimeScheduler; RCT_EXTERN NSArray *RCTAppSetupUnstableModulesRequiringMainQueueSetup( id dependencyProvider); -RCT_EXTERN id RCTAppSetupDefaultModuleFromClass( - Class moduleClass, - id dependencyProvider); +RCT_EXTERN id +RCTAppSetupDefaultModuleFromClass(Class moduleClass, id dependencyProvider, id rnInstanceId); std::unique_ptr RCTAppSetupDefaultJsExecutorFactory( RCTBridge *bridge, diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm index 8a89672bb8f3..76419182be29 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm @@ -57,7 +57,8 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) return dependencyProvider ? dependencyProvider.unstableModulesRequiringMainQueueSetup : @[]; } -id RCTAppSetupDefaultModuleFromClass(Class moduleClass, id dependencyProvider) +id +RCTAppSetupDefaultModuleFromClass(Class moduleClass, id dependencyProvider, id rnInstanceId) { // private block used to filter out modules depending on protocol conformance NSArray * (^extractModuleConformingToProtocol)(RCTModuleRegistry *, Protocol *) = @@ -111,6 +112,12 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) ] arrayByAddingObjectsFromArray:URLRequestHandlerModules]; }]; } + + // attempt to initialize with initWithUniqueRNInstance, which require the RN instance id for multi-instance support + if ([moduleClass instancesRespondToSelector:@selector(initWithUniqueRNInstance:)]) { + return [[moduleClass alloc] initWithUniqueRNInstance:rnInstanceId]; + } + // No custom initializer here. return [moduleClass new]; } diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm index b0cebc50bc08..eff4f929493b 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm @@ -8,6 +8,7 @@ #import "RCTReactNativeFactory.h" #import #import +#import #import #import #import @@ -32,18 +33,6 @@ using namespace facebook::react; -@interface DeallocationNotifier : NSObject -@property (nonatomic, copy) void (^onDealloc)(void); -@end - -@implementation DeallocationNotifier -- (void)dealloc -{ - if (self.onDealloc) - self.onDealloc(); -} -@end - @interface RCTReactNativeFactory () < RCTComponentViewFactoryComponentProvider, RCTHostDelegate, @@ -106,6 +95,7 @@ - (void)startReactNativeWithModuleName:(NSString *)moduleName [_delegate setRootView:rootView toRootViewController:rootViewController]; window.rootViewController = rootViewController; [window makeKeyAndVisible]; + [RCTMultiWindowRegistry registerWindow:window withRNInstance:[self.rootViewFactory.reactHost getRCTInstance]]; } #pragma mark - UIScene.ConnectionOptions @@ -260,7 +250,7 @@ - (Class)getModuleClassFromName:(const char *)name } } return RCTAppSetupDefaultModuleFromClass( - moduleClass, self.delegate.dependencyProvider); + moduleClass, self.delegate.dependencyProvider, [self.rootViewFactory.reactHost getRCTInstance]); } - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index 16828dd5d2f3..a335e1fe2eee 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -183,9 +183,11 @@ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge std::shared_ptr callInvoker = std::make_shared(_runtimeScheduler); - RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:_turboModuleManagerDelegate - jsInvoker:callInvoker]; + RCTTurboModuleManager *turboModuleManager = + [[RCTTurboModuleManager alloc] initWithBridge:bridge + delegate:_turboModuleManagerDelegate + jsInvoker:callInvoker + rnInstanceId:[self.reactHost getRCTInstance]]; _contextContainer->erase("RuntimeScheduler"); _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm index 7356b73523e2..b56a25ceb37a 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm @@ -27,7 +27,10 @@ + (BOOL)handleAppDelegateURL:(NSURL *)URL app:(UIApplication *)app; /// Posts a URL notification that will be handled by the emitter to JS; this method is used to invoke instance methods /// of RCTLinkingManager from class methods via NSNotificationCenter. /// @param URL The URL to be emitted. -+ (void)postNotificationWithURL:(NSURL *)URL; +/// @param sender The sender object, which is critical to differentiate the recipient instance. It should be the +/// RCTTurboModuleManagerDelegate instance that the event should be emitted to. Such design makes sure that only one RN +/// instance is the recipient of this event. ++ (void)postNotificationWithURL:(NSURL *)URL sender:(id)sender; @end @@ -35,10 +38,10 @@ @implementation RCTLinkingManager RCT_EXPORT_MODULE() -+ (void)postNotificationWithURL:(NSURL *)URL ++ (void)postNotificationWithURL:(NSURL *)URL sender:(id)sender { NSDictionary *payload = @{@"url" : URL.absoluteString}; - [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:nil userInfo:payload]; + [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:sender userInfo:payload]; } - (dispatch_queue_t)methodQueue @@ -53,7 +56,7 @@ - (void)startObserving [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURLNotification:) name:kOpenURLNotification - object:nil]; + object:self.windowForRNInstance]; } - (void)stopObserving @@ -88,7 +91,7 @@ + (BOOL)application:(UIApplication *)application restorationHandler:(nonnull void (^)(NSArray> *_Nullable))restorationHandler { if (!RCTIsSceneDelegateApp()) { - [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindow()]; + [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindowFromApplication(application)]; return YES; } @@ -99,7 +102,7 @@ + (BOOL)application:(UIApplication *)application + (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity { - [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindow()]; + [RCTLinkingManager handleUserActivity:userActivity window:RCTKeyWindowFromScene(scene)]; } + (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts @@ -109,7 +112,7 @@ + (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLC } NSURL *URL = URLContexts.allObjects.firstObject.URL; - [RCTLinkingManager postNotificationWithURL:URL]; + [RCTLinkingManager postNotificationWithURL:URL sender:RCTKeyWindowFromScene(scene)]; } #pragma mark - Common logic methods @@ -118,14 +121,14 @@ + (void)handleUserActivity:(NSUserActivity *)userActivity window:(UIWindow *)win { // This can be nullish when launching an App Clip. if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && userActivity.webpageURL != nil) { - [RCTLinkingManager postNotificationWithURL:userActivity.webpageURL]; + [RCTLinkingManager postNotificationWithURL:userActivity.webpageURL sender:window]; } } + (BOOL)handleAppDelegateURL:(NSURL *)URL app:(UIApplication *)app { if (!RCTIsSceneDelegateApp()) { - [RCTLinkingManager postNotificationWithURL:URL]; + [RCTLinkingManager postNotificationWithURL:URL sender:RCTKeyWindowFromApplication(app)]; return YES; } diff --git a/packages/react-native/React/Base/RCTBridgeModule.h b/packages/react-native/React/Base/RCTBridgeModule.h index 1fb3e3e0e7ef..79ca537014a2 100644 --- a/packages/react-native/React/Base/RCTBridgeModule.h +++ b/packages/react-native/React/Base/RCTBridgeModule.h @@ -10,6 +10,7 @@ #import #import +#import #import @@ -69,15 +70,32 @@ RCT_EXTERN_C_END * will be used as the JS module name. If omitted, the JS module name will * match the Objective-C class name. */ -#define RCT_EXPORT_MODULE(js_name) \ - RCT_EXTERN void RCTRegisterModule(Class); \ - +(NSString *)moduleName \ - { \ - return @ #js_name; \ - } \ - +(void)load \ - { \ - RCTRegisterModule(self); \ +#define RCT_EXPORT_MODULE(js_name) \ + RCT_EXTERN void RCTRegisterModule(Class); \ + +(NSString *)moduleName \ + { \ + return @ #js_name; \ + } \ + +(void)load \ + { \ + RCTRegisterModule(self); \ + } \ + @synthesize rnInstanceId = rnInstanceId; \ + -(UIWindow *)windowForRNInstance \ + { \ + return [RCTMultiWindowRegistry windowForRNInstance:self.rnInstanceId]; \ + } \ + -(instancetype)initWithUniqueRNInstance : (id)instanceId \ + { \ + /* for compatibility reasons, allow the init initializer to refer to the RN-instance-related properties, */ \ + /* even if the self object would be re-written later */ \ + self.rnInstanceId = instanceId; \ + self = [self init]; \ + if (self) { \ + /* a different self might've been returned from the designated initializer init */ \ + self.rnInstanceId = instanceId; \ + } \ + return self; \ } /** @@ -283,11 +301,14 @@ RCT_EXTERN_C_END /** * Like RCT_EXTERN_MODULE, but allows setting a custom JavaScript name. */ -#define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \ - objc_name : objc_supername @end @interface objc_name(RCTExternModule) \ - @end \ - @implementation objc_name (RCTExternModule) \ +#define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \ + objc_name: \ + objc_supername @ \ + end @interface objc_name(RCTExternModule) \ + @end \ + @implementation objc_name (RCTExternModule) \ RCT_EXPORT_MODULE_NO_LOAD(js_name, objc_name) +#import /** * Use this macro in accordance with RCT_EXTERN_MODULE to export methods @@ -348,6 +369,22 @@ RCT_EXTERN_C_END */ - (void)batchDidComplete RCT_DEPRECATED; +/// Convenience initializer that assigns the given `RCTInstance` as an instance property, which can be +/// helpful to obtain an id usable for `NSNotificationSender` to address only recipients in the same RN instance. +/// This initializer invokes the designated initializer `init` and assigns the instanceId both before and after calling +/// init, meaning that init designated initializer is safe to access self.instanceId. +- (instancetype)initWithUniqueRNInstance:(id)instanceId; + +/// Stores the `id` unique for this RN instance, in which this module is running. +/// +/// This unique identifier is an implementation detail of this class and while currently it is an `RCTInstance`, it is +/// not guaranteed to be stable. +@property (weak, nonatomic) id rnInstanceId; + +/// Returns the `UIWindow` associated with the React Native instance this module is running in. +/// @return The `UIWindow`; should never be null. +- (UIWindow *)windowForRNInstance; + @end /** diff --git a/packages/react-native/React/Base/RCTMultiWindowUtils.h b/packages/react-native/React/Base/RCTMultiWindowUtils.h new file mode 100644 index 000000000000..2910f82df235 --- /dev/null +++ b/packages/react-native/React/Base/RCTMultiWindowUtils.h @@ -0,0 +1,64 @@ +/* + * 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 + +#import "RCTLog.h" + +#pragma mark - AppDelegate utilities + +/// Utility function to get the key window from the UIApplication. +/// @param application The UIApplication instance. +/// @return The key window; theoretically could be nil if there would none - which should never happen. +static UIWindow *RCTKeyWindowFromApplication(UIApplication *application) +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + return application.keyWindow; +#pragma clang diagnostic pop +} + +#pragma mark - SceneDelegate utilities + +/// Utility function to get the key window from the UIScene. +/// @param scene The UIScene instance. +/// @return The key window; theoretically could be nil if there would none - which should never happen. +static UIWindow *RCTKeyWindowFromScene(UIScene *scene) +{ + if (![scene isKindOfClass:[UIWindowScene class]]) { + RCTLogError( + @"UIScene in RCTLinkingManager has not been a UIWindowScene. This should have never happened and is likely a bug."); + return nil; + } + return ((UIWindowScene *)scene).keyWindow; +} + +#pragma mark - RCTMultiWindowRegistry + +/// Registry singleton for mapping windows to corresponding delegate instances conforming to the `RCTTurboModuleManager` +/// protocol assigned to React Native instances in those windows. +/// +/// This is helpful for obtaining an `id` object that can be used as a unique token to identify the instance of React +/// Native tied to a given `UIWindow`. +/// +/// For instance, it is used in some `RCTEventEmitter` + `RCTBridgeModule` classes for dispatching emitter instance +/// methods from class methods on instances tied to given `UIWindow`s (RN instances) so that a native event originating +/// from a window is emitted only to the listener related to the RN instance running in that window. +@interface RCTMultiWindowRegistry : NSObject + +/// Registers a window tied to the given `id`. +/// @param window The UIWindow. +/// @param rnInstanceId A unique, stable id identifying the instance of RN running in the given window. +/// Native instance tied to the given window. ++ (void)registerWindow:(UIWindow *)window withRNInstance:(id)rnInstanceId; + +/// Returns the registered `UIWindow` for a given `id` representing a unique, stable id for a React Native instance. +/// @param rnInstanceId The RN instance id to query. +/// @return The registered UIWindow, or nil if none is registered. ++ (UIWindow *)windowForRNInstance:(id)rnInstanceId; + +@end diff --git a/packages/react-native/React/Base/RCTMultiWindowUtils.m b/packages/react-native/React/Base/RCTMultiWindowUtils.m new file mode 100644 index 000000000000..3a7842b6dfa8 --- /dev/null +++ b/packages/react-native/React/Base/RCTMultiWindowUtils.m @@ -0,0 +1,39 @@ +/* + * 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 + +#import + +#import "RCTMultiWindowUtils.h" + +@implementation RCTMultiWindowRegistry + ++ (NSMapTable *)rnInstanceIdToUIWindowRegistry +{ + static NSMapTable *registry = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + registry = [NSMapTable weakToWeakObjectsMapTable]; + }); + return registry; +} + ++ (void)registerWindow:(UIWindow *)window withRNInstance:(id)rnInstanceId +{ + RCTLogInfo(@"[RCTMultiWindowRegistry] Registering window %p with RN instance id %p", window, rnInstanceId); + [self.rnInstanceIdToUIWindowRegistry setObject:window forKey:rnInstanceId]; +} + +// no need for unregisterWindow-like, since the NSMapTable is weak-to-weak + ++ (UIWindow *)windowForRNInstance:(id)rnInstanceId +{ + return [self.rnInstanceIdToUIWindowRegistry objectForKey:rnInstanceId]; +} + +@end diff --git a/packages/react-native/React/CoreModules/RCTAlertController.h b/packages/react-native/React/CoreModules/RCTAlertController.h index 62adf2f3ac9e..cae9e99fc89b 100644 --- a/packages/react-native/React/CoreModules/RCTAlertController.h +++ b/packages/react-native/React/CoreModules/RCTAlertController.h @@ -9,6 +9,8 @@ @interface RCTAlertController : UIAlertController ++ (instancetype)alertControllerWithTitle:(NSString *)title inWindow:(UIWindow *)parentWindow; + - (void)show:(BOOL)animated completion:(void (^)(void))completion; - (void)hide; diff --git a/packages/react-native/React/CoreModules/RCTAlertController.mm b/packages/react-native/React/CoreModules/RCTAlertController.mm index b47ce0adefa0..b9bb475e12b7 100644 --- a/packages/react-native/React/CoreModules/RCTAlertController.mm +++ b/packages/react-native/React/CoreModules/RCTAlertController.mm @@ -17,10 +17,31 @@ @interface RCTAlertController () @implementation RCTAlertController +__weak UIWindow *weakParentWindow; + ++ (instancetype)alertControllerWithTitle:(NSString *)title inWindow:(UIWindow *)parentWindow +{ + RCTAlertController *instance = [super alertControllerWithTitle:title + message:nil + preferredStyle:UIAlertControllerStyleAlert]; + + weakParentWindow = parentWindow; + + return instance; +} + ++ (instancetype)alertControllerWithTitle:(NSString *)title + message:(NSString *)message + preferredStyle:(UIAlertControllerStyle)preferredStyle +{ + RCTAssert(NO, @"Do not use +alertControllerWithTitle:inWindow: instead"); + return nil; +} + - (UIWindow *)alertWindow { if (_alertWindow == nil) { - _alertWindow = [[UIWindow alloc] initWithWindowScene:RCTKeyWindow().windowScene]; + _alertWindow = [[UIWindow alloc] initWithWindowScene:weakParentWindow.windowScene]; if (_alertWindow) { _alertWindow.rootViewController = [UIViewController new]; @@ -35,7 +56,7 @@ - (void)show:(BOOL)animated completion:(void (^)(void))completion { UIUserInterfaceStyle style = self.overrideUserInterfaceStyle; if (style == UIUserInterfaceStyleUnspecified) { - UIUserInterfaceStyle overriddenStyle = RCTKeyWindow().overrideUserInterfaceStyle; + UIUserInterfaceStyle overriddenStyle = weakParentWindow.overrideUserInterfaceStyle; style = overriddenStyle ? overriddenStyle : UIUserInterfaceStyleUnspecified; } diff --git a/packages/react-native/React/CoreModules/RCTAlertManager.mm b/packages/react-native/React/CoreModules/RCTAlertManager.mm index 415bb1f6fb83..953cdf0a3798 100644 --- a/packages/react-native/React/CoreModules/RCTAlertManager.mm +++ b/packages/react-native/React/CoreModules/RCTAlertManager.mm @@ -105,9 +105,7 @@ - (void)invalidate } RCTExecuteOnMainQueue(^{ - RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title - message:nil - preferredStyle:UIAlertControllerStyleAlert]; + RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title inWindow:self.windowForRNInstance]; alertController.overrideUserInterfaceStyle = userInterfaceStyle; diff --git a/packages/react-native/React/CoreModules/RCTAppearance.mm b/packages/react-native/React/CoreModules/RCTAppearance.mm index d25d9f64e6bd..44a7fca6ed41 100644 --- a/packages/react-native/React/CoreModules/RCTAppearance.mm +++ b/packages/react-native/React/CoreModules/RCTAppearance.mm @@ -82,7 +82,7 @@ @implementation RCTAppearance { - (instancetype)init { if ((self = [super init])) { - UITraitCollection *traitCollection = RCTKeyWindow().traitCollection; + UITraitCollection *traitCollection = self.windowForRNInstance.traitCollection; _currentColorScheme = RCTColorSchemePreference(traitCollection); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appearanceChanged:) diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index 73721792589b..cad7a97e090e 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -30,8 +30,6 @@ @implementation RCTDeviceInfo { BOOL _isFullscreen; std::atomic _invalidated; NSDictionary *_constants; - - __weak UIWindow *_applicationWindow; } static NSString *const kFrameKeyPath = @"frame"; @@ -42,10 +40,7 @@ @implementation RCTDeviceInfo { - (instancetype)init { - if (self = [super init]) { - _applicationWindow = RCTKeyWindow(); - [_applicationWindow addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; - } + [self.windowForRNInstance addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; return self; } @@ -108,7 +103,7 @@ - (void)initialize #if TARGET_OS_IOS - _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; + _currentInterfaceOrientation = self.windowForRNInstance.windowScene.interfaceOrientation; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) @@ -159,7 +154,7 @@ - (void)_cleanupObservers [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTUserInterfaceStyleDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; - [_applicationWindow removeObserver:self forKeyPath:kFrameKeyPath]; + [self.windowForRNInstance removeObserver:self forKeyPath:kFrameKeyPath]; #if TARGET_OS_IOS [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; @@ -186,12 +181,23 @@ static BOOL RCTIsIPhoneNotched() return isIPhoneNotched; } +/** + * + */ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) +{ + return RCTExportedDimensions(fontScale); +} + +static NSDictionary *RCTExportedDimensions(CGFloat fontScale, UIView *mainWindow) { RCTAssertMainQueue(); UIScreen *mainScreen = UIScreen.mainScreen; CGSize screenSize = mainScreen.bounds.size; - UIView *mainWindow = RCTKeyWindow(); + + if (!mainWindow) { + mainWindow = RCTKeyWindow(); + } // We fallback to screen size if a key window is not found. CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize; @@ -223,7 +229,7 @@ - (NSDictionary *)_exportedDimensions // that accessibilityManager will eventually become available, js will eventually // be updated with the correct fontScale. CGFloat fontScale = accessibilityManager ? accessibilityManager.multiplier : 1.0; - return RCTExportedDimensions(fontScale); + return RCTExportedDimensions(fontScale, self.windowForRNInstance); } - (NSDictionary *)constantsToExport @@ -253,8 +259,7 @@ - (void)didReceiveNewContentSizeMultiplier - (void)interfaceOrientationDidChange { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - UIApplication *application = RCTSharedApplication(); - UIWindow *keyWindow = RCTKeyWindow(); + UIWindow *keyWindow = self.windowForRNInstance; UIInterfaceOrientation nextOrientation = keyWindow.windowScene.interfaceOrientation; BOOL isRunningInFullScreen = CGRectEqualToRect(keyWindow.frame, keyWindow.screen.bounds); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h index 33f3a8f84ec5..1851e2422bef 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h @@ -66,12 +66,14 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge delegate:(id)delegate - jsInvoker:(std::shared_ptr)jsInvoker; + jsInvoker:(std::shared_ptr)jsInvoker + rnInstanceId:(id)rnInstanceId; - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator delegate:(id)delegate - jsInvoker:(std::shared_ptr)jsInvoker; + jsInvoker:(std::shared_ptr)jsInvoker + rnInstanceId:(id)rnInstanceId; - (void)installJSBindings:(facebook::jsi::Runtime &)runtime; diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm index 5168bbf415d1..5243f757e4ce 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm @@ -217,6 +217,7 @@ @implementation RCTTurboModuleManager { RCTBridgeModuleDecorator *_bridgeModuleDecorator; dispatch_queue_t _sharedModuleQueue; + id _rnInstanceId; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -224,6 +225,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker + rnInstanceId:(id)rnInstanceId { if (self = [super init]) { _jsInvoker = std::move(jsInvoker); @@ -233,6 +235,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _bridgeModuleDecorator = bridgeModuleDecorator; _invalidating = false; _sharedModuleQueue = dispatch_queue_create("com.meta.react.turbomodulemanager.queue", DISPATCH_QUEUE_SERIAL); + _rnInstanceId = rnInstanceId; if (RCTTurboModuleInteropEnabled()) { // TODO(T174674274): Implement lazy loading of legacy modules in the new architecture. @@ -271,24 +274,28 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge - (instancetype)initWithBridge:(RCTBridge *)bridge delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker + rnInstanceId:(id)rnInstanceId { return [self initWithBridge:bridge bridgeProxy:nil bridgeModuleDecorator:[bridge bridgeModuleDecorator] delegate:delegate - jsInvoker:jsInvoker]; + jsInvoker:jsInvoker + rnInstanceId:rnInstanceId]; } - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker + rnInstanceId:(id)rnInstanceId { return [self initWithBridge:nil bridgeProxy:bridgeProxy bridgeModuleDecorator:bridgeModuleDecorator delegate:delegate - jsInvoker:jsInvoker]; + jsInvoker:jsInvoker + rnInstanceId:rnInstanceId]; } /** @@ -854,7 +861,11 @@ - (Class)_getModuleClassFromName:(const char *)moduleName } if (_legacyEagerlyRegisteredModuleClasses && _legacyEagerlyRegisteredModuleClasses[moduleNameStr]) { - return [_legacyEagerlyRegisteredModuleClasses[moduleNameStr] new]; + Class clazz = _legacyEagerlyRegisteredModuleClasses[moduleNameStr]; + if ([clazz instancesRespondToSelector:@selector(initWithUniqueRNInstance:)]) { + return [[clazz alloc] initWithUniqueRNInstance:_rnInstanceId]; + } + return [clazz new]; } id module = (id)[_delegate getModuleInstanceFromClass:moduleClass]; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h index c72cf7cdd6f6..e4fcb5726d55 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h @@ -74,6 +74,8 @@ typedef std::shared_ptr (^RCTHostJSEngineProv - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; +- (const RCTInstance *__nonnull)getRCTInstance; + @property (nonatomic, weak, nullable) id runtimeDelegate; @property (nonatomic, readonly) RCTSurfacePresenter *surfacePresenter; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm index 12631915e88d..aee719ca13e5 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm @@ -460,6 +460,11 @@ - (void)_reloadWithShouldRestartSurfaces:(BOOL)shouldRestartSurfaces } } +- (const RCTInstance *)getRCTInstance +{ + return _instance; +} + #pragma mark - jsinspector_modern - (jsinspector_modern::HostTarget *)inspectorTarget diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index f5e53529e420..723324e1b316 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -326,7 +326,8 @@ - (void)_start _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridgeProxy:bridgeProxy bridgeModuleDecorator:_bridgeModuleDecorator delegate:self - jsInvoker:jsCallInvoker]; + jsInvoker:jsCallInvoker + rnInstanceId:self]; #if RCT_DEV /** diff --git a/packages/rn-tester/NativeModuleExample/Screenshot.mm b/packages/rn-tester/NativeModuleExample/Screenshot.mm index ceb28ac6d067..741534856e33 100644 --- a/packages/rn-tester/NativeModuleExample/Screenshot.mm +++ b/packages/rn-tester/NativeModuleExample/Screenshot.mm @@ -11,20 +11,17 @@ @implementation ScreenshotManager -RCT_EXPORT_MODULE(); +RCT_EXPORT_MODULE() -RCT_EXPORT_METHOD(takeScreenshot - : (id /* NSString or NSNumber */)target withOptions - : (NSDictionary *)options resolve - : (RCTPromiseResolveBlock)resolve reject - : (RCTPromiseRejectBlock)reject) +RCT_EXPORT_METHOD(takeScreenshot : (id /* NSString or NSNumber */)target withOptions : (NSDictionary *) + options resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) { [self.bridge.uiManager addUIBlock:^( __unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { // Get view UIView *view; if (target == nil || [target isEqual:@"window"]) { - view = RCTKeyWindow(); + view = self.windowForRNInstance; } else if ([target isKindOfClass:[NSNumber class]]) { view = viewRegistry[target]; if (!view) { diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 74806755d520..1eeb01e88b3c 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -2711,7 +2711,7 @@ SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 - FBLazyVector: 1387c5e43d2d6b093cec8efb2e25cc0fac8ef30b + FBLazyVector: 85f78a7bc2dc00ac282908b6e1f1615646bb3df1 fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 013d35578e8c417727a1b441176629cfe051ad03 @@ -2720,74 +2720,74 @@ SPEC CHECKSUMS: OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf - RCTRequired: 77f28efe20e4d2c37103bccc333c0d110a30c268 - RCTTypeSafety: 963c6342a1a6988047fc2406e8b2e3095664c38a - React: 10b377126ff8e3814efb895e44af233746203eae - React-callinvoker: 8c0374c37f7f62218d1a37bf9c61fde47248a2e0 - React-Core: 66085076495d7daf06195060799a072262efa0ee - React-CoreModules: 2c161c09de16582257c15e7499dd76ea8e2dc12e - React-cxxreact: 51bebc3c68f1c732fe558ea5c1c4f776593a71b3 - React-debug: bc3231e6b793d17d18a771daaaabd389f588c6e2 - React-defaultsnativemodule: 42b80c99218d4eb7d69d73530619181e351f0944 - React-domnativemodule: 5093c5b3124152a9f1f0328b9d83896a385cd217 - React-Fabric: 8836cc32d509b93685269c23cf8c7cf3e5f71ab6 - React-FabricComponents: f99fb74642ce488eb9da39048537d1b34d5618ae - React-FabricImage: 4cb9574379135cca5bde5d68130376d4b7cdd775 - React-featureflags: 063077b799ac971730ed265cbb806ae37fdbc0bd - React-featureflagsnativemodule: aa451bcc59344491adf8dfe1afe24588204c4e4d - React-graphics: 09d687f4119f7ba6aa0d88a8a4ef7d677a9eeb4d - React-hermes: 1f8b853dbb2276e428e3a9442f50e7ad3ad0f656 - React-idlecallbacksnativemodule: f08b6e346c34ecc3b58b2c92604e4e750ef0bdbe - React-ImageManager: e752a44bc932a911f2641aa93074f3624cc06229 - React-jserrorhandler: 8f01fff0fc79a7ef682cf898764026b09b128360 - React-jsi: 828e75837067957a7229a9079806025c46e116f4 - React-jsiexecutor: b605ba028fc3a4e86c36ea2c59fac46ee25d04b6 - React-jsinspector: bdca03ccfe08a14b2fcaae6feb676df40bdd932e - React-jsinspectorcdp: 2fe3be3d89c2b005b2701606f33e0d2b44e0cf94 - React-jsinspectornetwork: c1b2537801416a72921d757f5c5c8895ff76541c - React-jsinspectortracing: 03a167475232364d26c2d765574fda8b1e0ecb14 - React-jsitooling: 1248a48cdd0da8577c7d8accc4c9e18dda2005e2 - React-jsitracing: cc8f3b2ad427357cbb9f512213f82d61bca85204 - React-logger: 2609fa3e4aa50ddcd34e1f7223dc0b9de8a8f1fc - React-Mapbuffer: 3a52bd35cad2b6e2b48a88da6fc61ee8096beded - React-microtasksnativemodule: dc91e479133dfff3e2c8f929ed5e0b4f48818754 - React-NativeModulesApple: 51186952811e19870d5942cd39f35e269f89761c - React-oscompat: b7e977877a716e520f0488cbdb0d5a1e209fb55e - React-perflogger: 889e1b94c66fb71984f5d014c50aaf10153e711c - React-performancecdpmetrics: 912b773aae7ca0a038c05a0d42b5d3a2bc906c5b - React-performancetimeline: 82e543de5d781de398b092b430ef12d05d39699b - React-RCTActionSheet: d0d1b20b35b1cdc5d11e3e0881b5895eb43eee42 - React-RCTAnimation: 2a7e9ac6cec544b34b636b23157b0ce1f167a841 - React-RCTAppDelegate: 058efed0e0b6290cf3bae12b2232cc60df885a2e - React-RCTBlob: 0220f5e83bf9bc92497223f9b43f476190de925e - React-RCTFabric: e22f35ba4a009b1e59256aebec2a57ebc1bda645 - React-RCTFBReactNativeSpec: 1b72d3a0a3bbdf671f01d47d2b07b580824fc6f6 - React-RCTImage: a71fd42b19ce4bab5be8370dfd93b60392ff1d84 - React-RCTLinking: 9f785f55e0ef7bea7029d57e93c4d2b196a0841d - React-RCTNetwork: 17926a4b47c591140e899146cbd0ce2fab23babf - React-RCTPushNotification: ccfe7cf75b4ac2d7a0139b274494f61366accfb2 - React-RCTRuntime: 7b851596bdaa140fbca41846f693a9f85d390878 - React-RCTSettings: d97acdbe2fb3829e96ae9453b9f4474ee4fbeb9b - React-RCTTest: 6eb6c600c810db52c3ef008ce28fb7abea7631d2 - React-RCTText: 4759b7427d5c98c17c1370b6a0746f9fa17932ec - React-RCTVibration: 18415fae9bd3c5a3b4ae2a3d0a096a16f3314594 - React-rendererconsistency: 0fe0a1d87d327738ec149d69d4dec4af42b61409 - React-renderercss: 8e80a281cd06aa52dd07c3df0e68b8708cbeca2a - React-rendererdebug: a4d5be536ac3672f922b1c6ce8da3aaead9a4efc - React-RuntimeApple: d83ef323a5f5b9d0454fc1377a9d287e9036b606 - React-RuntimeCore: 7c3382e041077c280e5b4efd481b1551057b16c0 - React-runtimeexecutor: 50aabe05827e11bac939b41065b52d41efac0db9 - React-RuntimeHermes: 784e63a0d4de27f4b6b1d3e7894edd6467dc309b - React-runtimescheduler: cc89da6b3b3c1e13fcc56351edad4eb3dd4aacf1 - React-timing: cdd0354b497ba5241973cbc64d6aa25ecc66aaa8 - React-utils: 01cba75aa61ea3a9b15fc3b2c7e03847505f790e - ReactAppDependencyProvider: f4c5c081b75cc7506854adf9c293bbb1902b434e + RCTRequired: 4184b5a403c6c8b986099e3b510d3d43e81292a9 + RCTTypeSafety: 7227ac39706fe85b232dc9ac06f2afe519e50e76 + React: e7e6d8be1a085229ae617f58ce663ecc03467c0f + React-callinvoker: d8effa85fdb6b3af99808e4fa70ac8793a63be2d + React-Core: 24ee190ecd48e02e12a74ba7619e9e5580d5b888 + React-CoreModules: acfc49e2c0d8c6714177e97b88d48167645a5712 + React-cxxreact: dc32da5fb4041e06f69c39dadf291fffa0cacbb8 + React-debug: 234c56c5965100aedcf69f821f0cf68a4d4d49e2 + React-defaultsnativemodule: 9f5dc0bd15da02be4630c76df1c0f44769f0045f + React-domnativemodule: f52a2594274c9fffe4b064eb1eef204462ec9658 + React-Fabric: 8790ff674e77f34f3de04939639439dc987a545f + React-FabricComponents: 210a7402cbbe3686377fc7256a8761a3e35a3467 + React-FabricImage: 7eab81b72e10c884a9035d8e03da65f9f202b592 + React-featureflags: 7c2bbc9202e2683f71f662254f8b426dd9c81c7d + React-featureflagsnativemodule: 03cdddc6845687dd3e217ad48805343592744845 + React-graphics: e9d015eb09ea6ea6e236d5ae268233892a88af12 + React-hermes: a64547fb0a2daeef2f23382ddf57553c5d535278 + React-idlecallbacksnativemodule: ec18f9fc8fbe78712b5c4e7efa1ac9bc294cde17 + React-ImageManager: 6a860bcee0750337879a67898030adf1e4bec0ba + React-jserrorhandler: 22eb6bd3ed30de4ea32624d46a449fa3e5ad8e8b + React-jsi: 5899ee834ba200c83acef51b394c53cfc5827703 + React-jsiexecutor: 79260131a246384e770607952d03467c9895329f + React-jsinspector: 7293cfad6df17ded38b64f144f1d950be7ba0a5b + React-jsinspectorcdp: da7c4a0d5b1f38c6587d88d565ce1821867ca6c1 + React-jsinspectornetwork: bc334d8e127f0ea1ac64936d3719d96a3e2de3a8 + React-jsinspectortracing: 353d6f3e5a9b8d9c9526080485067ca16740ff0f + React-jsitooling: c78c1cfc46ce3a8f7c82dd717e4a0e60ff93a27d + React-jsitracing: 755471976e34767895c47c4d6ad237ca489b394e + React-logger: 84a264679131e6b9efdfa7298bf15181bd36f8c2 + React-Mapbuffer: e96a3f83a62bd8c4f667df85f995b02c7ed4c662 + React-microtasksnativemodule: dbda6930b9646c5cb37e2b9d895c50b50fee3e8a + React-NativeModulesApple: 3d26f493ac4183955da18b9eaf8129972bc505fc + React-oscompat: b60711fbd18ada597aa9ea0928644b64a4c8214b + React-perflogger: ac7171a91ffd7146ae522a43672ed140ada473af + React-performancecdpmetrics: faa33ccc12cc29433d7d34c734b886d68cc3c269 + React-performancetimeline: ebe5033b1d861da2a746fe3e9a6df6c91945d941 + React-RCTActionSheet: cd100686e6ec7906e657189cd26e02ca11c2b710 + React-RCTAnimation: 7b0d52ff97d68d0477ae056d37600678541d1b4d + React-RCTAppDelegate: 5b6230637723a82dffaf80c9acf1505158327c95 + React-RCTBlob: a8ebecba5b5d5ee97d9d5f5ad7a38b365fe1884c + React-RCTFabric: ee1dda35c8f605393077ecbe77e5240ae1aedb43 + React-RCTFBReactNativeSpec: f8a697e965d48892d2d95437029898fb3437fbb6 + React-RCTImage: 8b329a0014bd09a49e171daf3fd51f5d036691a1 + React-RCTLinking: 9cfc7841cb213f4535deb65a40d8223944ea9c05 + React-RCTNetwork: 60fc46ad7319326c42e115d3e724e9ce427969ad + React-RCTPushNotification: 21f3d625d5781cf71f81c43362c20b4e505689d8 + React-RCTRuntime: dfbdde7e728504f15de1da2afcaf15e3b0c9a7ba + React-RCTSettings: 3feeafa3167bc7392d5f7b7fd69869f05a067b00 + React-RCTTest: 8fa3d151324703bbb4975380e9fd2b64cf98ae8e + React-RCTText: fd7f447afc6b5eff63613edda3f75ac1c3f3f554 + React-RCTVibration: a49ff944239d6b12f4041c078dc3debc86fb2e50 + React-rendererconsistency: 3ef0c2748b6542ea5b12627e88e92661107b515d + React-renderercss: ea9f8d8dcbb4bdadfa5a49d5913e3755fa55df1e + React-rendererdebug: 1fa717d81665825658eb4aa6f94f3029b78423d7 + React-RuntimeApple: 710a2b46c21f629cfc0273a46e12e466a36b273f + React-RuntimeCore: 32c142b13770be2f24704b5c91322f9abc3a1f35 + React-runtimeexecutor: 75287fefaa67b76f2be01c2a2fd98bde1cd0a399 + React-RuntimeHermes: c519c418c44ad756385416bcd2b9770a1bd56ba0 + React-runtimescheduler: 174f9cdd77a726291c0284324f0009df4957d0c5 + React-timing: 76a18d22300f6a2ae3d9a1e234c2c2a1d14eee51 + React-utils: ccce8473ff44410886c00f005ea5da9a18348e15 + ReactAppDependencyProvider: af0f8a13db7451021228c3ae6c5d397f0ef128d6 ReactCodegen: 5a2d9dbe44f2b16e06cbe68d2215d71776ae5c8b - ReactCommon: e955e436f41c7816dd74f5152a8f4d3a3d24b6f0 - ReactCommon-Samples: fe5e9d4aa17dda687a78d8fbb612468b9bb45575 + ReactCommon: 63528dc0a37b3d9370dd0119213d8fb9bed6082b + ReactCommon-Samples: 3aafed04815d317353cbd6d144529a42fdb909e8 ScreenshotManager: 370045f403c555760ae26d85a01dda89d257fa7b SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: fa211e60174f5ca5c8d58f830f9da3abf66878b7 + Yoga: e62fdc6acaa7e3cec94fa6b64b0afe870ced3de3 PODFILE CHECKSUM: 21be30d7d0e6382a4c9d45a5e70359e583b73403