Skip to content

Commit

Permalink
Enable fabric on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
terrysahaidak committed Aug 19, 2021
1 parent bab8428 commit 9e14f91
Show file tree
Hide file tree
Showing 7 changed files with 560 additions and 31 deletions.
12 changes: 10 additions & 2 deletions ios/FabricExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
3A21707CF8BA2A8317872206 /* libPods-FabricExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1187585E51CFC5B2853E13D6 /* libPods-FabricExample.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
866E8F6C31273213B04362D8 /* libPods-FabricExample-FabricExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 86110D4644D64952DF96D9C3 /* libPods-FabricExample-FabricExampleTests.a */; };
DE32070B26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h in Sources */ = {isa = PBXBuildFile; fileRef = DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */; };
DE32070C26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -42,6 +44,8 @@
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = FabricExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
86110D4644D64952DF96D9C3 /* libPods-FabricExample-FabricExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FabricExample-FabricExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FabricExampleTurboModuleProvider.h; path = FabricExample/FabricExampleTurboModuleProvider.h; sourceTree = "<group>"; };
DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = FabricExampleTurboModuleProvider.mm; path = FabricExample/FabricExampleTurboModuleProvider.mm; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
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>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -127,6 +131,8 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
DE32070926CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h */,
DE32070A26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm */,
13B07FAE1A68108700A75B9A /* FabricExample */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* FabricExampleTests */,
Expand Down Expand Up @@ -410,6 +416,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DE32070B26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.h in Sources */,
DE32070C26CEA50D0068A4DC /* FabricExampleTurboModuleProvider.mm in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
Expand Down Expand Up @@ -532,7 +540,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
Expand Down Expand Up @@ -597,7 +605,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
Expand Down
6 changes: 4 additions & 2 deletions ios/FabricExample/AppDelegate.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@class RCTBridge;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, readonly) RCTBridge *bridge;

@end
162 changes: 137 additions & 25 deletions ios/FabricExample/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTDataRequestHandler.h>
#import <React/RCTFileRequestHandler.h>
#import <React/RCTGIFImageDecoder.h>
#import <React/RCTHTTPRequestHandler.h>
#import <React/RCTImageLoader.h>
#import <React/RCTJSIExecutorRuntimeInstaller.h>
#import <React/RCTJavaScriptLoader.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTLocalAssetImageLoader.h>
#import <React/RCTNetworking.h>
#import <React/RCTRootView.h>
#import <React/JSCExecutorFactory.h>

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
Expand All @@ -11,52 +26,149 @@
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#endif

static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
#import <react/config/ReactNativeConfig.h>

#import <ReactCommon/RCTTurboModuleManager.h>

#import "FabricExampleTurboModuleProvider.h"


@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
RCTTurboModuleManager *_turboModuleManager;
}
#endif
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
InitializeFlipper(application);
#endif

RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"FabricExample"
initialProperties:nil];
RCTEnableTurboModule(YES);

if (@available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

NSDictionary *initProps = @{};

_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();

_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);

_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer];

_bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;

UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge
moduleName:@"FabricExample"
initialProperties:initProps];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[self initializeFlipper:application];
return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge


#ifdef FB_SONARKIT_ENABLED
- (void)initializeFlipper:(UIApplication *)application {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif


- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
}

- (void)loadSourceForBridge:(RCTBridge *)bridge
onProgress:(RCTSourceLoadProgressBlock)onProgress
onComplete:(RCTSourceLoadBlock)loadCallback
{
[RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback];
}

#pragma mark - RCTCxxBridgeDelegate

- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:self
jsInvoker:bridge.jsCallInvoker];
[bridge setRCTTurboModuleRegistry:_turboModuleManager];

#if RCT_DEV
/**
* Eagerly initialize RCTDevMenu so CMD + d, CMD + i, and CMD + r work.
* This is a stop gap until we have a system to eagerly init Turbo Modules.
*/
[_turboModuleManager moduleForName:"RCTDevMenu"];
#endif

__weak __typeof(self) weakSelf = self;
return std::make_unique<facebook::react::JSCExecutorFactory>(
facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge](facebook::jsi::Runtime &runtime) {
if (!bridge) {
return;
}
__typeof(self) strongSelf = weakSelf;
if (strongSelf) {
facebook::react::RuntimeExecutor syncRuntimeExecutor =
[&](std::function<void(facebook::jsi::Runtime & runtime_)> &&callback) { callback(runtime); };
[strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor];
}
}));
}

#pragma mark RCTTurboModuleManagerDelegate

- (Class)getModuleClassFromName:(const char *)name
{
return facebook::react::FabricExampleTurboModuleClassProvider(name);
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return facebook::react::FabricExampleTurboModuleProvider(name, jsInvoker);
}

- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
{
if (moduleClass == RCTImageLoader.class) {
return [[moduleClass alloc] initWithRedirectDelegate:nil
loadersProvider:^NSArray<id<RCTImageURLLoader>> *(RCTModuleRegistry * moduleRegistry) {
return @ [[RCTLocalAssetImageLoader new]];
}
decodersProvider:^NSArray<id<RCTImageDataDecoder>> *(RCTModuleRegistry * moduleRegistry) {
return @ [[RCTGIFImageDecoder new]];
}];
} else if (moduleClass == RCTNetworking.class) {
return [[moduleClass alloc] initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(RCTModuleRegistry * moduleRegistry) {
return @[
[RCTHTTPRequestHandler new],
[RCTDataRequestHandler new],
[RCTFileRequestHandler new],
];
}];
}
// No custom initializer here.
return [moduleClass new];
}

@end
24 changes: 24 additions & 0 deletions ios/FabricExample/FabricExampleTurboModuleProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <ReactCommon/RCTTurboModule.h>

namespace facebook {
namespace react {

/**
* Provide the TurboModule class for the given name.
*/
Class FabricExampleTurboModuleClassProvider(const char *name);

/**
* Provide a pure C++ instance of a TurboModule, specific to this app.
*/
std::shared_ptr<TurboModule> FabricExampleTurboModuleProvider(const std::string &name, std::shared_ptr<CallInvoker> jsInvoker);

} // namespace react
} // namespace facebook
26 changes: 26 additions & 0 deletions ios/FabricExample/FabricExampleTurboModuleProvider.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "FabricExampleTurboModuleProvider.h"

#import <React/CoreModulesPlugins.h>

// NOTE: This entire file should be codegen'ed.

namespace facebook {
namespace react {

Class FabricExampleTurboModuleClassProvider(const char *name) {
return RCTCoreModulesClassProvider(name);
}

std::shared_ptr<TurboModule> FabricExampleTurboModuleProvider(const std::string &name, std::shared_ptr<CallInvoker> jsInvoker) {
return nullptr;
}

} // namespace react
} // namespace facebook
2 changes: 1 addition & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ target 'FabricExample' do
:path => config[:reactNativePath],
# to enable hermes on iOS, change `false` to `true` and then install pods
:hermes_enabled => false,
:enable_fabric => true
:fabric_enabled => true
)

target 'FabricExampleTests' do
Expand Down
Loading

0 comments on commit 9e14f91

Please sign in to comment.