1// Copyright 2018-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXAppDelegateWrapper.h> 4#import <ExpoModulesCore/EXReactDelegateWrapper+Private.h> 5#import <ExpoModulesCore/Swift.h> 6 7 8@interface EXAppDelegateWrapper() 9 10@property (nonatomic, strong) EXReactDelegateWrapper *reactDelegate; 11 12@end 13 14@implementation EXAppDelegateWrapper { 15 EXExpoAppDelegate *_expoAppDelegate; 16} 17 18// Synthesize window, so the AppDelegate can synthesize it too. 19@synthesize window = _window; 20 21- (instancetype)init 22{ 23 if (self = [super init]) { 24 _expoAppDelegate = [[EXExpoAppDelegate alloc] init]; 25 _reactDelegate = [[EXReactDelegateWrapper alloc] initWithExpoReactDelegate:_expoAppDelegate.reactDelegate]; 26 } 27 return self; 28} 29 30// This needs to be implemented, otherwise forwarding won't be called. 31// When the app starts, `UIApplication` uses it to check beforehand 32// which `UIApplicationDelegate` selectors are implemented. 33- (BOOL)respondsToSelector:(SEL)selector 34{ 35 return [super respondsToSelector:selector] 36 || [_expoAppDelegate respondsToSelector:selector]; 37} 38 39// Forwards all invocations to `ExpoAppDelegate` object. 40- (id)forwardingTargetForSelector:(SEL)selector 41{ 42 return _expoAppDelegate; 43} 44 45#if __has_include(<React-RCTAppDelegate/RCTAppDelegate.h>) || __has_include(<React_RCTAppDelegate/RCTAppDelegate.h>) 46 47- (UIView *)findRootView:(UIApplication *)application 48{ 49 UIWindow *mainWindow = application.delegate.window; 50 if (mainWindow == nil) { 51 return nil; 52 } 53 UIViewController *rootViewController = mainWindow.rootViewController; 54 if (rootViewController == nil) { 55 return nil; 56 } 57 UIView *rootView = rootViewController.view; 58 return rootView; 59} 60 61- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 62{ 63 UIView *rootView = [self findRootView:application]; 64 // Backward compatible with react-native 0.71 running with legacy template, 65 // i.e. still creating bridge, rootView in AppDelegate.mm. 66 // In this case, we don't go through RCTAppDelegate's setup. 67 if (rootView == nil || ![rootView isKindOfClass:[RCTRootView class]]) { 68 [super application:application didFinishLaunchingWithOptions:launchOptions]; 69 [_expoAppDelegate application:application didFinishLaunchingWithOptions:launchOptions]; 70 } 71 return YES; 72} 73 74- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions 75{ 76 return [self.reactDelegate createBridgeWithDelegate:delegate launchOptions:launchOptions]; 77} 78 79- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge 80 moduleName:(NSString *)moduleName 81 initProps:(NSDictionary *)initProps 82{ 83 BOOL enableFabric = NO; 84#if RN_FABRIC_ENABLED 85 enableFabric = self.fabricEnabled; 86#endif 87 88 return [self.reactDelegate createRootViewWithBridge:bridge 89 moduleName:moduleName 90 initialProperties:initProps 91 fabricEnabled:enableFabric]; 92} 93 94- (UIViewController *)createRootViewController 95{ 96 return [self.reactDelegate createRootViewController]; 97} 98#endif // __has_include(<React-RCTAppDelegate/RCTAppDelegate.h>) 99 100@end 101