Skip to content

Commit 9e14f91

Browse files
committed
Enable fabric on iOS
1 parent bab8428 commit 9e14f91

File tree

7 files changed

+560
-31
lines changed

7 files changed

+560
-31
lines changed

ios/FabricExample.xcodeproj/project.pbxproj

+10-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
3A21707CF8BA2A8317872206 /* libPods-FabricExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1187585E51CFC5B2853E13D6 /* libPods-FabricExample.a */; };
1515
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
1616
866E8F6C31273213B04362D8 /* libPods-FabricExample-FabricExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 86110D4644D64952DF96D9C3 /* libPods-FabricExample-FabricExampleTests.a */; };
17+
DE32070B26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h in Sources */ = {isa = PBXBuildFile; fileRef = DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */; };
18+
DE32070C26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */; };
1719
/* End PBXBuildFile section */
1820

1921
/* Begin PBXContainerItemProxy section */
@@ -42,6 +44,8 @@
4244
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = FabricExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
4345
86110D4644D64952DF96D9C3 /* libPods-FabricExample-FabricExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FabricExample-FabricExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
4446
CB43910038FE645F788B211A /* Pods-FabricExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FabricExample.release.xcconfig"; path = "Target Support Files/Pods-FabricExample/Pods-FabricExample.release.xcconfig"; sourceTree = "<group>"; };
47+
DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FabricExampleTurboModuleProvider.h; path = FabricExample/FabricExampleTurboModuleProvider.h; sourceTree = "<group>"; };
48+
DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = FabricExampleTurboModuleProvider.mm; path = FabricExample/FabricExampleTurboModuleProvider.mm; sourceTree = "<group>"; };
4549
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
4650
F00065E4944EB1DB705AD658 /* Pods-FabricExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FabricExample.debug.xcconfig"; path = "Target Support Files/Pods-FabricExample/Pods-FabricExample.debug.xcconfig"; sourceTree = "<group>"; };
4751
/* End PBXFileReference section */
@@ -127,6 +131,8 @@
127131
83CBB9F61A601CBA00E9B192 = {
128132
isa = PBXGroup;
129133
children = (
134+
DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */,
135+
DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */,
130136
13B07FAE1A68108700A75B9A /* FabricExample */,
131137
832341AE1AAA6A7D00B99B32 /* Libraries */,
132138
00E356EF1AD99517003FC87E /* FabricExampleTests */,
@@ -410,6 +416,8 @@
410416
isa = PBXSourcesBuildPhase;
411417
buildActionMask = 2147483647;
412418
files = (
419+
DE32070B26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h in Sources */,
420+
DE32070C26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm in Sources */,
413421
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
414422
13B07FC11A68108700A75B9A /* main.m in Sources */,
415423
);
@@ -532,7 +540,7 @@
532540
buildSettings = {
533541
ALWAYS_SEARCH_USER_PATHS = NO;
534542
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
535-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
543+
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
536544
CLANG_CXX_LIBRARY = "libc++";
537545
CLANG_ENABLE_MODULES = YES;
538546
CLANG_ENABLE_OBJC_ARC = YES;
@@ -597,7 +605,7 @@
597605
buildSettings = {
598606
ALWAYS_SEARCH_USER_PATHS = NO;
599607
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
600-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
608+
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
601609
CLANG_CXX_LIBRARY = "libc++";
602610
CLANG_ENABLE_MODULES = YES;
603611
CLANG_ENABLE_OBJC_ARC = YES;

ios/FabricExample/AppDelegate.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
#import <React/RCTBridgeDelegate.h>
21
#import <UIKit/UIKit.h>
32

4-
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
3+
@class RCTBridge;
4+
5+
@interface AppDelegate : UIResponder <UIApplicationDelegate>
56

67
@property (nonatomic, strong) UIWindow *window;
8+
@property (nonatomic, readonly) RCTBridge *bridge;
79

810
@end

ios/FabricExample/AppDelegate.mm

+137-25
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
#import "AppDelegate.h"
22

33
#import <React/RCTBridge.h>
4+
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
5+
#import <React/RCTSurfacePresenter.h>
6+
#import <React/RCTSurfacePresenterBridgeAdapter.h>
47
#import <React/RCTBundleURLProvider.h>
8+
#import <React/RCTCxxBridgeDelegate.h>
9+
#import <React/RCTDataRequestHandler.h>
10+
#import <React/RCTFileRequestHandler.h>
11+
#import <React/RCTGIFImageDecoder.h>
12+
#import <React/RCTHTTPRequestHandler.h>
13+
#import <React/RCTImageLoader.h>
14+
#import <React/RCTJSIExecutorRuntimeInstaller.h>
15+
#import <React/RCTJavaScriptLoader.h>
16+
#import <React/RCTLinkingManager.h>
17+
#import <React/RCTLocalAssetImageLoader.h>
18+
#import <React/RCTNetworking.h>
519
#import <React/RCTRootView.h>
20+
#import <React/JSCExecutorFactory.h>
621

722
#ifdef FB_SONARKIT_ENABLED
823
#import <FlipperKit/FlipperClient.h>
@@ -11,52 +26,149 @@
1126
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
1227
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
1328
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
29+
#endif
1430

15-
static void InitializeFlipper(UIApplication *application) {
16-
FlipperClient *client = [FlipperClient sharedClient];
17-
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
18-
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
19-
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
20-
[client addPlugin:[FlipperKitReactPlugin new]];
21-
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
22-
[client start];
31+
#import <react/config/ReactNativeConfig.h>
32+
33+
#import <ReactCommon/RCTTurboModuleManager.h>
34+
35+
#import "FabricExampleTurboModuleProvider.h"
36+
37+
38+
@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
39+
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
40+
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
41+
facebook::react::ContextContainer::Shared _contextContainer;
42+
RCTTurboModuleManager *_turboModuleManager;
2343
}
24-
#endif
44+
@end
2545

2646
@implementation AppDelegate
2747

2848
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
2949
{
30-
#ifdef FB_SONARKIT_ENABLED
31-
InitializeFlipper(application);
32-
#endif
3350

34-
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
35-
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
36-
moduleName:@"FabricExample"
37-
initialProperties:nil];
51+
RCTEnableTurboModule(YES);
3852

39-
if (@available(iOS 13.0, *)) {
40-
rootView.backgroundColor = [UIColor systemBackgroundColor];
41-
} else {
42-
rootView.backgroundColor = [UIColor whiteColor];
43-
}
53+
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
54+
55+
NSDictionary *initProps = @{};
56+
57+
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
58+
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
59+
60+
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
61+
62+
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer];
63+
64+
_bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
4465

66+
UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge
67+
moduleName:@"FabricExample"
68+
initialProperties:initProps];
69+
4570
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4671
UIViewController *rootViewController = [UIViewController new];
4772
rootViewController.view = rootView;
4873
self.window.rootViewController = rootViewController;
4974
[self.window makeKeyAndVisible];
75+
[self initializeFlipper:application];
5076
return YES;
5177
}
5278

53-
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
79+
80+
81+
#ifdef FB_SONARKIT_ENABLED
82+
- (void)initializeFlipper:(UIApplication *)application {
83+
FlipperClient *client = [FlipperClient sharedClient];
84+
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
85+
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
86+
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
87+
[client addPlugin:[FlipperKitReactPlugin new]];
88+
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
89+
[client start];
90+
}
91+
#endif
92+
93+
94+
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
5495
{
55-
#if DEBUG
5696
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
57-
#else
58-
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
97+
}
98+
99+
- (void)loadSourceForBridge:(RCTBridge *)bridge
100+
onProgress:(RCTSourceLoadProgressBlock)onProgress
101+
onComplete:(RCTSourceLoadBlock)loadCallback
102+
{
103+
[RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback];
104+
}
105+
106+
#pragma mark - RCTCxxBridgeDelegate
107+
108+
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
109+
{
110+
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
111+
delegate:self
112+
jsInvoker:bridge.jsCallInvoker];
113+
[bridge setRCTTurboModuleRegistry:_turboModuleManager];
114+
115+
#if RCT_DEV
116+
/**
117+
* Eagerly initialize RCTDevMenu so CMD + d, CMD + i, and CMD + r work.
118+
* This is a stop gap until we have a system to eagerly init Turbo Modules.
119+
*/
120+
[_turboModuleManager moduleForName:"RCTDevMenu"];
59121
#endif
122+
123+
__weak __typeof(self) weakSelf = self;
124+
return std::make_unique<facebook::react::JSCExecutorFactory>(
125+
facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge](facebook::jsi::Runtime &runtime) {
126+
if (!bridge) {
127+
return;
128+
}
129+
__typeof(self) strongSelf = weakSelf;
130+
if (strongSelf) {
131+
facebook::react::RuntimeExecutor syncRuntimeExecutor =
132+
[&](std::function<void(facebook::jsi::Runtime & runtime_)> &&callback) { callback(runtime); };
133+
[strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor];
134+
}
135+
}));
136+
}
137+
138+
#pragma mark RCTTurboModuleManagerDelegate
139+
140+
- (Class)getModuleClassFromName:(const char *)name
141+
{
142+
return facebook::react::FabricExampleTurboModuleClassProvider(name);
143+
}
144+
145+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
146+
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
147+
{
148+
return facebook::react::FabricExampleTurboModuleProvider(name, jsInvoker);
149+
}
150+
151+
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
152+
{
153+
if (moduleClass == RCTImageLoader.class) {
154+
return [[moduleClass alloc] initWithRedirectDelegate:nil
155+
loadersProvider:^NSArray<id<RCTImageURLLoader>> *(RCTModuleRegistry * moduleRegistry) {
156+
return @ [[RCTLocalAssetImageLoader new]];
157+
}
158+
decodersProvider:^NSArray<id<RCTImageDataDecoder>> *(RCTModuleRegistry * moduleRegistry) {
159+
return @ [[RCTGIFImageDecoder new]];
160+
}];
161+
} else if (moduleClass == RCTNetworking.class) {
162+
return [[moduleClass alloc] initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(RCTModuleRegistry * moduleRegistry) {
163+
return @[
164+
[RCTHTTPRequestHandler new],
165+
[RCTDataRequestHandler new],
166+
[RCTFileRequestHandler new],
167+
];
168+
}];
169+
}
170+
// No custom initializer here.
171+
return [moduleClass new];
60172
}
61173

62174
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <ReactCommon/RCTTurboModule.h>
9+
10+
namespace facebook {
11+
namespace react {
12+
13+
/**
14+
* Provide the TurboModule class for the given name.
15+
*/
16+
Class FabricExampleTurboModuleClassProvider(const char *name);
17+
18+
/**
19+
* Provide a pure C++ instance of a TurboModule, specific to this app.
20+
*/
21+
std::shared_ptr<TurboModule> FabricExampleTurboModuleProvider(const std::string &name, std::shared_ptr<CallInvoker> jsInvoker);
22+
23+
} // namespace react
24+
} // namespace facebook
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "FabricExampleTurboModuleProvider.h"
9+
10+
#import <React/CoreModulesPlugins.h>
11+
12+
// NOTE: This entire file should be codegen'ed.
13+
14+
namespace facebook {
15+
namespace react {
16+
17+
Class FabricExampleTurboModuleClassProvider(const char *name) {
18+
return RCTCoreModulesClassProvider(name);
19+
}
20+
21+
std::shared_ptr<TurboModule> FabricExampleTurboModuleProvider(const std::string &name, std::shared_ptr<CallInvoker> jsInvoker) {
22+
return nullptr;
23+
}
24+
25+
} // namespace react
26+
} // namespace facebook

ios/Podfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ target 'FabricExample' do
1010
:path => config[:reactNativePath],
1111
# to enable hermes on iOS, change `false` to `true` and then install pods
1212
:hermes_enabled => false,
13-
:enable_fabric => true
13+
:fabric_enabled => true
1414
)
1515

1616
target 'FabricExampleTests' do

0 commit comments

Comments
 (0)