xref: /expo/ios/Exponent/ExpoKit/ExpoKit.m (revision 09a2a2f1)
1// Copyright 2015-present 650 Industries. All rights reserved.
2
3#import "ExpoKit.h"
4#import "EXViewController.h"
5#import "EXBuildConstants.h"
6#import "EXEnvironment.h"
7#import "EXKernel.h"
8#import "EXKernelUtil.h"
9#import "EXKernelLinkingManager.h"
10#import "EXReactAppExceptionHandler.h"
11#import "EXRemoteNotificationManager.h"
12
13#import <ExpoModulesCore/EXModuleRegistryProvider.h>
14
15#import <GoogleMaps/GoogleMaps.h>
16
17
18@interface ExpoKit ()
19{
20  Class _rootViewControllerClass;
21}
22
23@property (nonatomic, nullable, strong) EXViewController *rootViewController;
24@property (nonatomic, strong) NSDictionary *launchOptions;
25
26@end
27
28@implementation ExpoKit
29
30+ (nonnull instancetype)sharedInstance
31{
32  static ExpoKit *theExpoKit = nil;
33  static dispatch_once_t once;
34  dispatch_once(&once, ^{
35    if (!theExpoKit) {
36      theExpoKit = [[ExpoKit alloc] init];
37    }
38  });
39  return theExpoKit;
40}
41
42- (instancetype)init
43{
44  if (self = [super init]) {
45    _rootViewControllerClass = [EXViewController class];
46    [self _initDefaultKeys];
47  }
48  return self;
49}
50
51- (void)dealloc
52{
53  [[NSNotificationCenter defaultCenter] removeObserver:self];
54}
55
56- (void)registerRootViewControllerClass:(Class)rootViewControllerClass
57{
58  NSAssert([rootViewControllerClass isSubclassOfClass:[EXViewController class]], @"ExpoKit root view controller class must subclass EXViewController.");
59  _rootViewControllerClass = rootViewControllerClass;
60}
61
62- (EXViewController *)rootViewController
63{
64  if (!_rootViewController) {
65    _rootViewController = [[_rootViewControllerClass alloc] init];
66    _rootViewController.delegate = [EXKernel sharedInstance];
67  }
68  return _rootViewController;
69}
70
71- (UIViewController *)currentViewController
72{
73  EXViewController *rootViewController = [self rootViewController];
74  UIViewController *controller = [rootViewController contentViewController];
75  while (controller.presentedViewController != nil) {
76    controller = controller.presentedViewController;
77  }
78  return controller;
79}
80
81- (void)prepareWithLaunchOptions:(nullable NSDictionary *)launchOptions
82{
83  [DDLog addLogger:[DDOSLogger sharedInstance]];
84  RCTSetFatalHandler(handleFatalReactError);
85
86  NSString *standaloneGMSKey = [[NSBundle mainBundle].infoDictionary objectForKey:@"GMSApiKey"];
87  if (standaloneGMSKey && standaloneGMSKey.length) {
88    [GMSServices provideAPIKey:standaloneGMSKey];
89  } else {
90    if (_applicationKeys[@"GOOGLE_MAPS_IOS_API_KEY"]) {// we may define this as empty
91      if ([_applicationKeys[@"GOOGLE_MAPS_IOS_API_KEY"] length]) {
92        [GMSServices provideAPIKey:_applicationKeys[@"GOOGLE_MAPS_IOS_API_KEY"]];
93      }
94    }
95  }
96
97  _launchOptions = launchOptions;
98}
99
100#pragma mark - internal
101
102- (void)_initDefaultKeys
103{
104  // these are provided in the expo/expo open source repo as defaults; they can all be overridden by setting
105  // the `applicationKeys` property on ExpoKit.
106  if ([EXBuildConstants sharedInstance].defaultApiKeys) {
107    self.applicationKeys = [EXBuildConstants sharedInstance].defaultApiKeys;
108  }
109}
110
111@end
112