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