Skip to content

Commit

Permalink
feat: add Swift entrypoint
Browse files Browse the repository at this point in the history
[wip] add module maps to some RN modules to allow for swift c++ imports

feat: implement RCTReactController and RCTSwiftUIAppDelegate

feat: introduce new method to RCTAppDelegate
  • Loading branch information
okwasniewski committed Jan 15, 2024
1 parent 474980e commit 2e08709
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 110 deletions.
5 changes: 4 additions & 1 deletion packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)bridgelessEnabled;

/// Return the bundle URL for the main bundle.
- (NSURL *)bundleURL;
- (NSURL *__nullable)bundleURL;

/// Don't use this method, it's going to be removed soon.
- (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary*)initialProperties launchOptions:(NSDictionary*)launchOptions;

@end

Expand Down
91 changes: 51 additions & 40 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -83,51 +83,16 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
{
RCTSetNewArchEnabled([self newArchEnabled]);
BOOL enableTM = self.turboModuleEnabled;
BOOL fabricEnabled = self.fabricEnabled;
BOOL enableBridgeless = self.bridgelessEnabled;

NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled);

RCTAppSetupPrepareApp(application, enableTM, *_reactNativeConfig);

UIView *rootView;
if (enableBridgeless) {
// Enable native view config interop only if both bridgeless mode and Fabric is enabled.
RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled);

// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);

[self createReactHost];
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps];

RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];

rootView = (RCTRootView *)surfaceHostingProxyRootView;
} else {
if (!self.bridge) {
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions];
}
if ([self newArchEnabled]) {
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge
contextContainer:_contextContainer];
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;

[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
}
rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps];
}

[self customizeRootView:(RCTRootView *)rootView];

#if TARGET_OS_VISION
self.window = [[UIWindow alloc] initWithFrame:RCTForegroundWindow().bounds];
/// Bail out of UIWindow initializaiton to support multi-window scenarios in SwiftUI lifecycle.
return YES;
#else
UIView* rootView = [self viewWithModuleName:self.moduleName initialProperties:[self prepareInitialProps] launchOptions:launchOptions];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
#endif

UIViewController *rootViewController = [self createRootViewController];
[self setRootView:rootView toRootViewController:rootViewController];
Expand All @@ -136,13 +101,59 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
[self.window makeKeyAndVisible];

return YES;
#endif
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Noop
}

- (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary*)initialProperties launchOptions:(NSDictionary*)launchOptions {
BOOL fabricEnabled = self.fabricEnabled;
BOOL enableBridgeless = self.bridgelessEnabled;

NSDictionary *initProps = updateInitialProps(initialProperties, fabricEnabled);

UIView *rootView;
if (enableBridgeless) {
// Enable native view config interop only if both bridgeless mode and Fabric is enabled.
RCTSetUseNativeViewConfigsInBridgelessMode(self.fabricEnabled);

// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);

[self createReactHost];
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps];

RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];

rootView = (RCTRootView *)surfaceHostingProxyRootView;
} else {
if (!self.bridge) {
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions];
}
if ([self newArchEnabled]) {
if (!self.bridgeAdapter) {
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge
contextContainer:_contextContainer];
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;

[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
}
}
rootView = [self createRootViewWithBridge:self.bridge moduleName:moduleName initProps:initProps];
}

[self customizeRootView:(RCTRootView *)rootView];

return rootView;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
[NSException raise:@"RCTBridgeDelegate::sourceURLForBridge not implemented"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#elif __has_include(<reacthermes/HermesExecutorFactory.h>)
#import <reacthermes/HermesExecutorFactory.h>
#endif
#else // USE_HERMES
#elif __has_include(<React/JSCExecutorFactory.h>) // USE_HERMES
#import <React/JSCExecutorFactory.h>
#endif // USE_HERMES

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@interface RCTReactViewController : UIViewController

@property (nonatomic, strong) NSString *_Nonnull moduleName;
@property (nonatomic, strong) NSDictionary *_Nullable initialProps;

- (instancetype _Nonnull)initWithModuleName:(NSString *_Nonnull)moduleName
initProps:(NSDictionary *_Nullable)initProps;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#import "RCTReactViewController.h"
#import <React/RCTUtils.h>

#import "RCTAppDelegate.h"

@implementation RCTReactViewController

- (instancetype)initWithModuleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
if (self = [super init]) {
_moduleName = moduleName;
_initialProps = initProps;
}
return self;
}

// TODO: Temporary solution for creating RCTRootView. This should be done through factory pattern, here: https://github.com/facebook/react-native/pull/42263
- (void)loadView {
id<UIApplicationDelegate> appDelegate = RCTSharedApplication().delegate;
if ([appDelegate respondsToSelector:@selector(viewWithModuleName:initialProperties:launchOptions:)]) {
RCTAppDelegate *delegate = (RCTAppDelegate *)appDelegate;
self.view = [delegate viewWithModuleName:_moduleName initialProperties:_initialProps launchOptions:@{}];
} else {
[NSException raise:@"UIApplicationDelegate:viewWithModuleName:initialProperties:launchOptions: not implemented"
format:@"Make sure you subclass RCTAppDelegate"];
}
}

@end
2 changes: 1 addition & 1 deletion packages/react-native/React/Base/RCTBridgeDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
* When running from a locally bundled JS file, this should be a `file://` url
* pointing to a path inside the app resources, e.g. `file://.../main.jsbundle`.
*/
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge;
- (NSURL *__nullable)sourceURLForBridge:(RCTBridge *)bridge;

@optional

Expand Down
20 changes: 12 additions & 8 deletions packages/react-native/React/Base/RCTBundleURLProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ RCT_EXTERN const NSUInteger kRCTBundleURLProviderDefaultPort;
RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
#endif

NS_ASSUME_NONNULL_BEGIN

@interface RCTBundleURLProvider : NSObject

/**
Expand Down Expand Up @@ -58,38 +60,38 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
* Returns the jsBundleURL for a given bundle entrypoint and
* the fallback offline JS bundle if the packager is not running.
*/
- (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:(NSURL * (^)(void))fallbackURLProvider;
- (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:(NSURL * (^)(void))fallbackURLProvider;

/**
* Returns the jsBundleURL for a given split bundle entrypoint in development
*/
- (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot;
- (NSURL *__nullable)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot;

/**
* Returns the jsBundleURL for a given bundle entrypoint and
* the fallback offline JS bundle if the packager is not running.
* if extension is nil, "jsbundle" will be used.
*/
- (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackExtension:(NSString *)extension;
- (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackExtension:(NSString *)extension;

/**
* Returns the jsBundleURL for a given bundle entrypoint and
* the fallback offline JS bundle if the packager is not running.
*/
- (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot;
- (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot;

/**
* Returns the jsBundleURL for a given bundle entrypoint and
* the fallback offline JS bundle. If extension is nil,
* "jsbundle" will be used.
*/
- (NSURL *)jsBundleURLForFallbackExtension:(NSString *)extension;
- (NSURL *__nullable)jsBundleURLForFallbackExtension:(NSString *)extension;

/**
* Returns the resourceURL for a given bundle entrypoint and
* the fallback offline resource file if the packager is not running.
*/
- (NSURL *)resourceURLForResourceRoot:(NSString *)root
- (NSURL *__nullable)resourceURLForResourceRoot:(NSString *)root
resourceName:(NSString *)name
resourceExtension:(NSString *)extension
offlineBundle:(NSBundle *)offlineBundle;
Expand Down Expand Up @@ -124,13 +126,13 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
* - runModule: When true, will run the main module after defining all modules. This is used in the main bundle but not
* in split bundles.
*/
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
+ (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap;

+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
+ (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
packagerScheme:(NSString *)scheme
enableDev:(BOOL)enableDev
Expand Down Expand Up @@ -160,3 +162,5 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
queryItems:(NSArray<NSURLQueryItem *> *)queryItems;

@end

NS_ASSUME_NONNULL_END
3 changes: 2 additions & 1 deletion packages/react-native/React/CoreModules/RCTAppearance.mm
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ @implementation RCTAppearance {
- (instancetype)init
{
if ((self = [super init])) {
UITraitCollection *traitCollection = RCTSharedApplication().delegate.window.traitCollection;
// TODO: Remove this after merging this PR upstream: https://github.com/facebook/react-native/pull/42231
UITraitCollection *traitCollection = RCTKeyWindow().traitCollection;
_currentColorScheme = RCTColorSchemePreference(traitCollection);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appearanceChanged:)
Expand Down
96 changes: 48 additions & 48 deletions packages/rn-tester/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ CHECKOUT OPTIONS:
SPEC CHECKSUMS:
boost: 8f1e9b214fa11f71081fc8ecd5fad3daf221cf7f
DoubleConversion: 71bf0761505a44e4dfddc0aa04afa049fdfb63b5
FBLazyVector: 5fdead7fff97d43aacf320bcccb748cf8527af07
FBLazyVector: 7398875239b8f10f3c4ca88abadcdafed3ef1fc8
fmt: 5d9ffa7ccba126c08b730252123601d514652320
glog: 4f05d17aa39a829fee878689fc9a41af587fabba
hermes-engine: 3fed7e58e811ae8f795063cc6450714395c0276d
Expand All @@ -1424,56 +1424,56 @@ SPEC CHECKSUMS:
OCMock: 267d92c078398b7ce11d99e811e3a402744c06bc
RCT-Folly: d8c13e288297f63c0db8f083cfedebdd2649a299
RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf
RCTRequired: 6b32de28a5215a5990284d541bbdec8b5e3c78bf
RCTTypeSafety: 0e2bb3047d531a60b28b1d0d63e0c27a742a3019
React: a6f80cd5ba07887121f8b480991e17041a838f5c
React-callinvoker: d558dab7c4d987f1577838a50d59aeb069130d91
RCTRequired: 48f050ad972df064e6de48ae6361f5c086958b78
RCTTypeSafety: f28e9e4cd9ffca2e70515eefc7a6a4c03909572b
React: 717c0bd48a74275e44e482594b810d19f27908e0
React-callinvoker: 06410c883c85ffe8ef56a680c22df4f39c390ccc
React-Codegen: 04a9ac6fd2f392534ed432102c6cbf117dcbf62b
React-Core: 6403b0d9390e408017e82dc7823e059c53186141
React-CoreModules: 6406001452f46e9234a2fac3861a60786285acc0
React-cxxreact: f917d87380150aaaf8053fb4280358aad33c9b71
React-debug: c12ba28faf2c0aace7cbc81d7ac7661075976460
React-Fabric: 1d2070e13efd26fa34bb67cf484794265402ac06
React-FabricImage: 238905c6db0cf533d562b52ae936bfd7ed5f00dc
React-graphics: c430227a30690a86be35a8fb8c4c36ff312ff4bc
React-hermes: f6b54c8b4553fc7a8926f3e46459923a834a99d4
React-ImageManager: 38795ba06968bbcb11343b9e1123557af34c6270
React-jserrorhandler: fba402f8090b05e29c57c7bb111413e12e89aebe
React-jsi: d5643763df3910249aac671c9b7d634e6e96af7b
React-jsiexecutor: 847a90333a8840846652833aa4e291e433277aec
React-jsinspector: c2abef5095276eeb09c4b871f3024851d2ac3e58
React-jsitracing: 3f24b1171cc7aa986555a84e1036d3a6ba98bc84
React-logger: 4b1ded6e5707b276ffd58505987aba8dd1c0c3e4
React-Mapbuffer: b562329b31a9a5e3f18a8b4632c4fa8945a504e8
React-nativeconfig: 86b0961752d6a00ccc30418bfb5bfb5ebda84149
React-NativeModulesApple: eb4d247f32f25df62d1e979721502203db3de17c
React-perflogger: 31792e118e9c4785739c1823a481d64ba3d512b9
React-RCTActionSheet: a79621f1907340e31a66a4ad5e89175ef13f4215
React-RCTAnimation: 1f6948befc38688ecd5e78b7afd7d356aafa79b3
React-RCTAppDelegate: 9b0ecae938c894f4678a5e4726c03a06e92b0d93
React-RCTBlob: afaf18b4618c4d71095dfae9fca7c548dbcf0da0
React-RCTFabric: 0e96635634399a9ccf6c3c7fb18d5bac8e2561d5
React-RCTImage: 280f6f62a88f13253013ab5709e7bc60259cc081
React-RCTLinking: 9757d922aaa9aea2baa6e6178a8b1f08c1a85add
React-RCTNetwork: 92e96ad358d83b5a809e6222987c77106f44691e
React-RCTPushNotification: 36ec0c6d3ab1195665c49c0cfd689864401cc111
React-RCTSettings: 758a24aefbee012d903ca4f80532e95edfe2b516
React-RCTTest: a30b88c8910a259ef769af7654b1812668019b22
React-RCTText: ff85a26056ca9a34198934774e0f75ac2305c2c0
React-RCTVibration: 5086b14f98c2255e71cc6a2213b6f67338dcdff4
React-rendererdebug: 6e0021971efb40a76f807b913fdba6ec3ecabbd0
React-rncore: 27b4d75d116e9ae44292dc26aecff5bbad9e6996
React-RuntimeApple: c18cc85bf03a322efd2a76fd48f4c693d6901e67
React-RuntimeCore: 631803674e2884b5d866aacac96850191a081e1a
React-runtimeexecutor: a6b1c771b522e49e6906c5354b0e8859a64e7b3e
React-RuntimeHermes: 1473abdead583d8ab788ebd31de9c8e81e19d0fc
React-runtimescheduler: 1b905cb65942a3bfdff3f003c9c778b6b46afca6
React-utils: a5c7207b3bd558fdbfc553ea7a7731fbfc7f3552
ReactCommon: 2c87b20987de3a37d3993e4c1cab34fb97c28899
ReactCommon-Samples: e95d8d284b23ed4eda37498eaa460b6468c24699
React-Core: 054771ce6d549c74df4da7d856aab7e082f607e3
React-CoreModules: 0d9b7d4eaf736f7c2edf644b069d0b9fbc7cf0e7
React-cxxreact: ef427ce10de85992fbbe5ff2d742798888eafeda
React-debug: 88536e62244a930f199aa23d6317ec70332a7331
React-Fabric: 5b54cc3156824745b09b0688e8afff7610675c29
React-FabricImage: 3a4b3056a1307e4241fd71f757ca59c1f4fa02b1
React-graphics: 9de3a20a755496173834a6149a93926143dac36f
React-hermes: 103aba271edccff06efdec54dcb47d207c3f801c
React-ImageManager: ea7f173cb3585fd3665403260aa1d2d3f255b844
React-jserrorhandler: 2227bd12a6728c7be99d6db5666bfc84cf2df194
React-jsi: 9b23219207c76cfcfe153bc92e26247544bdc619
React-jsiexecutor: bb92399809b9998869ad6d271804f446318a4ed9
React-jsinspector: 75a80380afb500104bee9ac053bdbacfeb17ceaa
React-jsitracing: c6901bb0257cd15a9733d11ce6b9558487b8f47e
React-logger: fb080c7e6684db8c195688eb56793f77b69a8d34
React-Mapbuffer: 5140c0edceb347d371b9e42b5fa57367e1da35bb
React-nativeconfig: 307b5d697cc50c23f6b526768fbab7be7e9b63cf
React-NativeModulesApple: 2cf3e29bbbe16a5b712160b1ad4af06e3349c54f
React-perflogger: 3752f5d10c3b65a7f02352b3573e099cec341a6f
React-RCTActionSheet: f3322ee445d630b1572e06f002dade53299c1e0c
React-RCTAnimation: f25448672aac10fd2a2731df46789f790ced2508
React-RCTAppDelegate: e8e759be431ee92405189c13b997d05256946fa4
React-RCTBlob: d9b14e27ed43556282650fa1c8289625d0c3b2b1
React-RCTFabric: e8eb7fa3f260c730734135b2291bae2bcfbc2999
React-RCTImage: 2e27346aea7af6e5ced8bb5241e7d9038a0bb6f7
React-RCTLinking: c87acaa37a901511af5d17931e58559debfde168
React-RCTNetwork: 4e936b1f553d2f296283ad58900f6ad8dda85428
React-RCTPushNotification: b89c023865e1945b95598f52d6cdde772a700849
React-RCTSettings: 642668034997a60903a53da770321be25bd7b9b0
React-RCTTest: adba00c7500cccaa618c23870e8d882acc9bb0ef
React-RCTText: 19c2fe3781e00fc96f7993c18f6fa64b8582ac0b
React-RCTVibration: 19dccc5057ad3f915a6a9678a57f9641bd9c1e60
React-rendererdebug: 5e21b910056185378f0ae4c4215c6af258d29092
React-rncore: 79390384fa0541f8ad0ebcc1f89f177c4c4988da
React-RuntimeApple: 50724334961379a320b12e0fe1d49583f16b7f31
React-RuntimeCore: 6de3b61abdc2a700cd253d1d6a5a4cfe9032ca62
React-runtimeexecutor: 9d74940931e749f1a1385d14bbdfe1d939a41162
React-RuntimeHermes: df97a05151582bc77382f0041a83220ec9779f8b
React-runtimescheduler: b0ffe9de1135d0882bdd819d282cc33f8d3a4b42
React-utils: 7ddb7f20506b8311841b2058e7883e3ca5ceefd9
ReactCommon: ae82e3782d09704b0e8fd2298720bc7d6b6163d0
ReactCommon-Samples: e7fbc94445e784afb3fa04c42f0ba3dbfc567e0c
ScreenshotManager: a5f596498de38f3cf3377df636ca67355503f190
SocketRocket: 0ba3e799f983d2dfa878777017659ef6c866e5c6
Yoga: e4691eb7881cae15f847654cf06b0f7962707af0
Yoga: 014dbde7260e2bd7aa62d540ba0b28bf1274b6d4

PODFILE CHECKSUM: 7e999b8158f1055609ef4491bc35f1ad658fdd6c

Expand Down
Loading

0 comments on commit 2e08709

Please sign in to comment.