Skip to content

Commit

Permalink
Add function to customise RootView in Bridgeless (#42088)
Browse files Browse the repository at this point in the history
Summary:

This change adds an extra function to customise the RootView in both Bridge and Bridgeless mode.
To nudge users in a migration, we also add a warning message for next version that should push our users to migrate away from the old implementation to the new one.
*The Warning is shown ONLY when the user do customise the rootView*. For users which were not customising the Root View, the warning will not appear.

The documentation of the new method plus the warning should guide the users toward the right migration path.

## Changelog
[iOS][Added] - Added the customiseRootView method which is called in both bridge and bridgeless. Added also a warning for 0.74 with instructions on how to migrate.

Reviewed By: cortinico

Differential Revision: D52442598
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Jan 2, 2024
1 parent af8c56a commit edb9e9b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@class RCTBridge;
@protocol RCTBridgeDelegate;
@protocol RCTComponentViewProtocol;
@class RCTRootView;
@class RCTSurfacePresenterBridgeAdapter;

/**
Expand Down Expand Up @@ -86,6 +87,26 @@
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps;
/**
* This method can be used to customize the rootView that is passed to React Native.
* A typical example is to override this method in the AppDelegate to change the background color.
* To achieve this, add in your `AppDelegate.mm`:
* ```
* - (void)customizeRootView:(RCTRootView *)rootView
* {
* rootView.backgroundColor = [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) {
* if ([traitCollection userInterfaceStyle] == UIUserInterfaceStyleDark) {
* return [UIColor blackColor];
* } else {
* return [UIColor whiteColor];
* }
* }];
* }
* ```
*
* @parameter: rootView - The root view to customize.
*/
- (void)customizeRootView:(RCTRootView *)rootView;

/**
* It creates the RootViewController.
Expand Down
22 changes: 22 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#import "RCTAppDelegate.h"
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
Expand Down Expand Up @@ -117,6 +118,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
}
rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps];
}
[self customizeRootView:(RCTRootView *)rootView];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [self createRootViewController];
[self setRootView:rootView toRootViewController:rootViewController];
Expand Down Expand Up @@ -144,10 +146,16 @@ - (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOp
return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions];
}

- (void)customizeRootView:(RCTRootView *)rootView
{
// Override point for customization after application launch.
}

- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps
{
[self _logWarnIfCreateRootViewWithBridgeIsOverridden];
BOOL enableFabric = self.fabricEnabled;
UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric);

Expand All @@ -156,6 +164,20 @@ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
return rootView;
}

- (void)_logWarnIfCreateRootViewWithBridgeIsOverridden
{
SEL selector = @selector(createRootViewWithBridge:moduleName:initProps:);
IMP baseClassImp = method_getImplementation(class_getInstanceMethod([RCTAppDelegate class], selector));
IMP currentClassImp = method_getImplementation(class_getInstanceMethod([self class], selector));
if (currentClassImp != baseClassImp) {
NSString *warnMessage =
@"If you are using the `createRootViewWithBridge` to customize the root view appearence,"
"for example to set the backgroundColor, please migrate to `customiseView` method.\n"
"The `createRootViewWithBridge` method is not invoked in bridgeless.";
RCTLogWarn(@"%@", warnMessage);
}
}

- (UIViewController *)createRootViewController
{
return [UIViewController new];
Expand Down

0 comments on commit edb9e9b

Please sign in to comment.