From f22a5ef4ed12a37d87d76b534770ca414ff1d015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Thu, 26 Sep 2024 05:39:01 -0700 Subject: [PATCH] feat: improve RCTAppDelegate usage for brownfield (#46625) Summary: This PR improves the usage of `RCTAppDelegate` for brownfield scenarios. Currently, when we want to integrate React Native with a brownfield app users might not want to initialize React Native in the main window. They may want to create it later. Example usage: ```swift class AppDelegate: RCTAppDelegate { override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Disable automatically creating react native window self.automaticallyLoadReactNativeWindow = false return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ``` ```swift import Foundation import React import React_RCTAppDelegate class SettingsViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.view = (RCTSharedApplication()?.delegate as? RCTAppDelegate)?.rootViewFactory .view(withModuleName: "Settings", initialProperties: [:]) } } ``` ## Changelog: [IOS] [ADDED] - improve RCTAppDelegate usage for brownfield, add `automaticallyLoadReactNativeWindow` flag Pull Request resolved: https://github.com/facebook/react-native/pull/46625 Test Plan: CI Green Reviewed By: cortinico Differential Revision: D63325397 Pulled By: cipolleschi fbshipit-source-id: 1361bda5fcd91f4933219871c64a84a83c281c34 --- .../Libraries/AppDelegate/RCTAppDelegate.h | 3 ++ .../Libraries/AppDelegate/RCTAppDelegate.mm | 34 +++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index fd7310c7f88..f9ca86a602a 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -64,6 +64,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) NSDictionary *initialProps; @property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; +/// If `automaticallyLoadReactNativeWindow` is set to `true`, the React Native window will be loaded automatically. +@property (nonatomic, assign) BOOL automaticallyLoadReactNativeWindow; + @property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; /** diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 1e87756cad8..ca5be139ffb 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -12,6 +12,7 @@ #import #import #import +#include #import #import #import @@ -38,6 +39,14 @@ @implementation RCTAppDelegate +- (instancetype)init +{ + if (self = [super init]) { + _automaticallyLoadReactNativeWindow = YES; + } + return self; +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self _setUpFeatureFlags]; @@ -47,23 +56,28 @@ RCTAppSetupPrepareApp(application, self.turboModuleEnabled); self.rootViewFactory = [self createRCTRootViewFactory]; - - UIView *rootView = [self.rootViewFactory viewWithModuleName:self.moduleName - initialProperties:self.initialProps - launchOptions:launchOptions]; - if (self.newArchEnabled || self.fabricEnabled) { [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; } + if (self.automaticallyLoadReactNativeWindow) { + [self loadReactNativeWindow:launchOptions]; + } + + return YES; +} + +- (void)loadReactNativeWindow:(NSDictionary *)launchOptions +{ + UIView *rootView = [self.rootViewFactory viewWithModuleName:self.moduleName + initialProperties:self.initialProps + launchOptions:launchOptions]; + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [self createRootViewController]; [self setRootView:rootView toRootViewController:rootViewController]; - self.window.rootViewController = rootViewController; - self.window.windowScene.delegate = self; - [self.window makeKeyAndVisible]; - - return YES; + _window.rootViewController = rootViewController; + [_window makeKeyAndVisible]; } - (void)applicationDidEnterBackground:(UIApplication *)application