Browse Source

ios native refactor to remove the singleton hell step 1

Daniel Zlotin 7 years ago
parent
commit
e083cd812c

+ 0
- 1
ios/RNN.h View File

8
 
8
 
9
 @interface RNN : NSObject
9
 @interface RNN : NSObject
10
 
10
 
11
-@property (readonly) BOOL isReadyToReceiveCommands;
12
 @property (readonly) RCTBridge* bridge;
11
 @property (readonly) RCTBridge* bridge;
13
 @property (readonly) RNNEventEmitter* eventEmitter;
12
 @property (readonly) RNNEventEmitter* eventEmitter;
14
 @property (readonly) RNNStore *store;
13
 @property (readonly) RNNStore *store;

+ 30
- 17
ios/RNN.m View File

5
 #import <React/RCTBridge.h>
5
 #import <React/RCTBridge.h>
6
 #import "RNNSplashScreen.h"
6
 #import "RNNSplashScreen.h"
7
 
7
 
8
-@interface RNN()
8
+#import "RNNBridgeModule.h"
9
+#import "RNNReactRootViewCreator.h"
9
 
10
 
11
+@interface RNN() <RCTBridgeDelegate>
12
+
13
+@property NSURL* jsCodeLocation;
10
 @property (readwrite) RCTBridge* bridge;
14
 @property (readwrite) RCTBridge* bridge;
11
-@property (readwrite) BOOL isReadyToReceiveCommands;
12
 @property (readwrite) RNNEventEmitter* eventEmitter;
15
 @property (readwrite) RNNEventEmitter* eventEmitter;
13
 
16
 
14
 @property (readwrite) RNNStore *store;
17
 @property (readwrite) RNNStore *store;
36
 }
39
 }
37
 
40
 
38
 
41
 
39
--(void)bootstrap:(NSURL *)jsCodeLocation launchOptions:(NSDictionary *)launchOptions
40
-{
42
+-(void)bootstrap:(NSURL *)jsCodeLocation launchOptions:(NSDictionary *)launchOptions {
43
+	self.jsCodeLocation = jsCodeLocation;
41
 	self.eventEmitter = [RNNEventEmitter new];
44
 	self.eventEmitter = [RNNEventEmitter new];
42
 	
45
 	
43
 	UIApplication.sharedApplication.delegate.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
46
 	UIApplication.sharedApplication.delegate.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
46
 	[RNNSplashScreen show];
49
 	[RNNSplashScreen show];
47
 	
50
 	
48
 	[self registerForJsEvents];
51
 	[self registerForJsEvents];
52
+	
49
 	// this will load the JS bundle
53
 	// this will load the JS bundle
50
-	self.bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation moduleProvider:nil launchOptions:launchOptions];
54
+	self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
51
 }
55
 }
52
 
56
 
57
+# pragma mark - RCTBridgeDelegate
53
 
58
 
54
-# pragma mark private
55
-
59
+-(NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
60
+	return self.jsCodeLocation;
61
+}
56
 
62
 
57
--(void)registerForJsEvents
58
-{
59
-	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onJavaScriptLoaded) name:RCTJavaScriptDidLoadNotification object:self.bridge];
60
-	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onJavaScriptWillLoad) name:RCTJavaScriptWillStartLoadingNotification	object:self.bridge];
63
+-(NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
64
+	
65
+	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:[RNNReactRootViewCreator new] store:self.store];
66
+	RNNCommandsHandler* commandsHandler = [[RNNCommandsHandler alloc]initWithStore:[RNN instance].store controllerFactory:controllerFactory];
67
+	
68
+	RNNBridgeModule* bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:commandsHandler];
69
+	return @[bridgeModule];
61
 }
70
 }
62
 
71
 
72
+# pragma mark - private
63
 
73
 
64
--(void)onJavaScriptLoaded
65
-{
66
-	self.isReadyToReceiveCommands = true;
67
-	[self.eventEmitter sendOnAppLaunched];
74
+-(void)registerForJsEvents {
75
+	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onJavaScriptLoaded) name:RCTJavaScriptDidLoadNotification object:self.bridge];
76
+	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onJavaScriptWillLoad) name:RCTJavaScriptWillStartLoadingNotification	object:self.bridge];
68
 }
77
 }
69
 
78
 
70
 
79
 
71
--(void)onJavaScriptWillLoad
72
-{
80
+-(void)onJavaScriptWillLoad {
73
 	self.store = [RNNStore new];
81
 	self.store = [RNNStore new];
74
 	[self resetRootViewControllerOnlyOnJSDevReload];
82
 	[self resetRootViewControllerOnlyOnJSDevReload];
75
 }
83
 }
76
 
84
 
85
+-(void)onJavaScriptLoaded {
86
+	self.store.isReadyToReceiveCommands = true;
87
+	[self.eventEmitter sendOnAppLaunched];
88
+}
89
+
77
 -(void)resetRootViewControllerOnlyOnJSDevReload {
90
 -(void)resetRootViewControllerOnlyOnJSDevReload {
78
 	if(![UIApplication.sharedApplication.delegate.window.rootViewController isKindOfClass:[RNNSplashScreen class]]) {
91
 	if(![UIApplication.sharedApplication.delegate.window.rootViewController isKindOfClass:[RNNSplashScreen class]]) {
79
 		UIApplication.sharedApplication.delegate.window.rootViewController = nil;
92
 		UIApplication.sharedApplication.delegate.window.rootViewController = nil;

+ 4
- 0
ios/RNNBridgeModule.h View File

3
 
3
 
4
 #import <React/RCTBridgeModule.h>
4
 #import <React/RCTBridgeModule.h>
5
 
5
 
6
+#import "RNNCommandsHandler.h"
7
+
6
 @interface RNNBridgeModule : NSObject <RCTBridgeModule>
8
 @interface RNNBridgeModule : NSObject <RCTBridgeModule>
7
 
9
 
10
+-(instancetype)initWithCommandsHandler:(RNNCommandsHandler*)commandsHandler;
11
+
8
 @end
12
 @end

+ 15
- 7
ios/RNNBridgeModule.m View File

1
 #import "RNNBridgeModule.h"
1
 #import "RNNBridgeModule.h"
2
 
2
 
3
-#import "RNNCommandsHandler.h"
3
+@interface RNNBridgeModule ()
4
+@property RNNCommandsHandler* commandsHandler;
5
+@end
4
 
6
 
5
 @implementation RNNBridgeModule
7
 @implementation RNNBridgeModule
6
 
8
 
10
 	return dispatch_get_main_queue();
12
 	return dispatch_get_main_queue();
11
 }
13
 }
12
 
14
 
15
+-(instancetype)initWithCommandsHandler:(RNNCommandsHandler *)commandsHandler {
16
+	self = [super init];
17
+	self.commandsHandler = commandsHandler;
18
+	return self;
19
+}
20
+
13
 #pragma mark - JS interface
21
 #pragma mark - JS interface
14
 
22
 
15
 RCT_EXPORT_METHOD(setRoot:(NSDictionary*)layout) {
23
 RCT_EXPORT_METHOD(setRoot:(NSDictionary*)layout) {
16
-	[[RNNCommandsHandler new] setRoot:layout];
24
+	[self.commandsHandler setRoot:layout];
17
 }
25
 }
18
 
26
 
19
 RCT_EXPORT_METHOD(push:(NSString*)containerId layout:(NSDictionary*)layout) {
27
 RCT_EXPORT_METHOD(push:(NSString*)containerId layout:(NSDictionary*)layout) {
20
-	[[RNNCommandsHandler new] push:containerId layout:layout];
28
+	[self.commandsHandler push:containerId layout:layout];
21
 }
29
 }
22
 
30
 
23
 RCT_EXPORT_METHOD(pop:(NSString*)containerId) {
31
 RCT_EXPORT_METHOD(pop:(NSString*)containerId) {
24
-	[[RNNCommandsHandler new] pop:containerId];
32
+	[self.commandsHandler pop:containerId];
25
 }
33
 }
26
 
34
 
27
 RCT_EXPORT_METHOD(showModal:(NSDictionary*)layout) {
35
 RCT_EXPORT_METHOD(showModal:(NSDictionary*)layout) {
28
-	[[RNNCommandsHandler new] showModal:layout];
36
+	[self.commandsHandler showModal:layout];
29
 }
37
 }
30
 
38
 
31
 RCT_EXPORT_METHOD(dismissModal:(NSString*)containerId) {
39
 RCT_EXPORT_METHOD(dismissModal:(NSString*)containerId) {
32
-	[[RNNCommandsHandler new] dismissModal:containerId];
40
+	[self.commandsHandler dismissModal:containerId];
33
 }
41
 }
34
 
42
 
35
 RCT_EXPORT_METHOD(dismissAllModals) {
43
 RCT_EXPORT_METHOD(dismissAllModals) {
36
-	[[RNNCommandsHandler new] dismissAllModals];
44
+	[self.commandsHandler dismissAllModals];
37
 }
45
 }
38
 
46
 
39
 @end
47
 @end

+ 6
- 2
ios/RNNCommandsHandler.h View File

1
-
2
-
3
 #import <Foundation/Foundation.h>
1
 #import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+
4
+#import "RNNControllerFactory.h"
5
+#import "RNNStore.h"
4
 
6
 
5
 @interface RNNCommandsHandler : NSObject
7
 @interface RNNCommandsHandler : NSObject
6
 
8
 
9
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory;
10
+
7
 -(void) setRoot:(NSDictionary*)layout;
11
 -(void) setRoot:(NSDictionary*)layout;
8
 
12
 
9
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout;
13
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout;

+ 34
- 21
ios/RNNCommandsHandler.m View File

1
 
1
 
2
 #import "RNNCommandsHandler.h"
2
 #import "RNNCommandsHandler.h"
3
 
3
 
4
-
5
-#import "RNN.h"
6
-#import "RNNControllerFactory.h"
7
-#import "RNNReactRootViewCreator.h"
8
-#import "RNNStore.h"
9
 #import "RNNModalManager.h"
4
 #import "RNNModalManager.h"
10
 #import "RNNNavigationStackManager.h"
5
 #import "RNNNavigationStackManager.h"
11
 
6
 
7
+@interface RNNCommandsHandler ()
8
+@property RNNControllerFactory *controllerFactory;
9
+@property RNNStore *store;
10
+@end
11
+
12
 @implementation RNNCommandsHandler
12
 @implementation RNNCommandsHandler
13
 
13
 
14
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory {
15
+	self = [super init];
16
+	self.store = store;
17
+	self.controllerFactory = controllerFactory;
18
+	return self;
19
+}
20
+
14
 #pragma mark - public
21
 #pragma mark - public
15
 
22
 
16
 -(void) setRoot:(NSDictionary*)layout {
23
 -(void) setRoot:(NSDictionary*)layout {
17
 	[self assertReady];
24
 	[self assertReady];
18
-	RNNControllerFactory *factory = [[RNNControllerFactory alloc] initWithRootViewCreator:[RNNReactRootViewCreator new] store:[RNN instance].store];
19
-	UIViewController *vc = [factory createLayoutAndSaveToStore:layout];
25
+	UIViewController *vc = [self.controllerFactory createLayoutAndSaveToStore:layout];
20
 	
26
 	
21
 	UIApplication.sharedApplication.delegate.window.rootViewController = vc;
27
 	UIApplication.sharedApplication.delegate.window.rootViewController = vc;
22
 	[UIApplication.sharedApplication.delegate.window makeKeyAndVisible];
28
 	[UIApplication.sharedApplication.delegate.window makeKeyAndVisible];
24
 
30
 
25
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout {
31
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout {
26
 	[self assertReady];
32
 	[self assertReady];
27
-	RNNControllerFactory *factory = [[RNNControllerFactory alloc] initWithRootViewCreator:[RNNReactRootViewCreator new] store:[RNN instance].store];
28
-	UIViewController *newVc = [factory createLayoutAndSaveToStore:layout];
29
-	UIViewController *vc = [[RNN instance].store findContainerForId:containerId];
30
 	
33
 	
31
-	[[[RNNNavigationStackManager alloc] initWithStore:[RNN instance].store] push:newVc onTop:vc animated:YES];
34
+	UIViewController *newVc = [self.controllerFactory createLayoutAndSaveToStore:layout];
35
+	
36
+	// find on who to push
37
+	UIViewController *vc = [self.store findContainerForId:containerId];
38
+	
39
+	// do the actual pushing
40
+	[[[RNNNavigationStackManager alloc] initWithStore:self.store] push:newVc onTop:vc animated:YES];
32
 }
41
 }
33
 
42
 
34
 -(void) pop:(NSString*)containerId {
43
 -(void) pop:(NSString*)containerId {
35
 	[self assertReady];
44
 	[self assertReady];
36
-	UIViewController *vc = [[RNN instance].store findContainerForId:containerId];
37
-	[[[RNNNavigationStackManager alloc] initWithStore:[RNN instance].store] pop:vc animated:YES];
38
-	[[RNN instance].store removeContainer:containerId];
45
+	
46
+	// find who to pop
47
+	UIViewController *vc = [self.store findContainerForId:containerId];
48
+	
49
+	// do the popping
50
+	[[[RNNNavigationStackManager alloc] initWithStore:self.store] pop:vc animated:YES];
51
+	[self.store removeContainer:containerId];
39
 }
52
 }
40
 
53
 
41
 -(void) showModal:(NSDictionary*)layout {
54
 -(void) showModal:(NSDictionary*)layout {
42
 	[self assertReady];
55
 	[self assertReady];
43
-	RNNControllerFactory *factory = [[RNNControllerFactory alloc] initWithRootViewCreator:[RNNReactRootViewCreator new] store:[RNN instance].store];
44
-	UIViewController *newVc = [factory createLayoutAndSaveToStore:layout];
45
-	[[[RNNModalManager alloc] initWithStore:[RNN instance].store] showModal:newVc];
56
+	
57
+	UIViewController *newVc = [self.controllerFactory createLayoutAndSaveToStore:layout];
58
+	[[[RNNModalManager alloc] initWithStore:self.store] showModal:newVc];
46
 }
59
 }
47
 
60
 
48
 -(void) dismissModal:(NSString*)containerId {
61
 -(void) dismissModal:(NSString*)containerId {
49
 	[self assertReady];
62
 	[self assertReady];
50
-	[[[RNNModalManager alloc] initWithStore:[RNN instance].store] dismissModal:containerId];
63
+	[[[RNNModalManager alloc] initWithStore:self.store] dismissModal:containerId];
51
 }
64
 }
52
 
65
 
53
 -(void) dismissAllModals {
66
 -(void) dismissAllModals {
54
 	[self assertReady];
67
 	[self assertReady];
55
-	[[[RNNModalManager alloc] initWithStore:[RNN instance].store] dismissAllModals];
68
+	[[[RNNModalManager alloc] initWithStore:self.store] dismissAllModals];
56
 }
69
 }
57
 
70
 
58
 #pragma mark - private
71
 #pragma mark - private
59
 
72
 
60
-- (void)assertReady {
61
-	if (![RNN instance].isReadyToReceiveCommands) {
73
+-(void) assertReady {
74
+	if (!self.store.isReadyToReceiveCommands) {
62
 		@throw [NSException exceptionWithName:@"BridgeNotLoadedError" reason:@"Bridge not yet loaded! Send commands after Navigation.events().onAppLaunched() has been called." userInfo:nil];
75
 		@throw [NSException exceptionWithName:@"BridgeNotLoadedError" reason:@"Bridge not yet loaded! Send commands after Navigation.events().onAppLaunched() has been called." userInfo:nil];
63
 	}
76
 	}
64
 }
77
 }

+ 6
- 12
ios/RNNControllerFactory.m View File

25
 	return self;
25
 	return self;
26
 }
26
 }
27
 
27
 
28
-- (UIViewController*)createLayoutAndSaveToStore:(NSDictionary*)layout
29
-{
28
+- (UIViewController*)createLayoutAndSaveToStore:(NSDictionary*)layout {
30
 	return [self fromTree:layout];
29
 	return [self fromTree:layout];
31
 }
30
 }
32
 
31
 
33
 # pragma mark private
32
 # pragma mark private
34
 
33
 
35
-- (UIViewController*)fromTree:(NSDictionary*)json
36
-{
34
+- (UIViewController*)fromTree:(NSDictionary*)json {
37
 	RNNLayoutNode* node = [RNNLayoutNode create:json];
35
 	RNNLayoutNode* node = [RNNLayoutNode create:json];
38
 	
36
 	
39
 	UIViewController* result;
37
 	UIViewController* result;
74
 	return result;
72
 	return result;
75
 }
73
 }
76
 
74
 
77
-- (RNNRootViewController*)createContainer:(RNNLayoutNode*)node
78
-{
75
+- (RNNRootViewController*)createContainer:(RNNLayoutNode*)node {
79
 	return [[RNNRootViewController alloc] initWithNode:node rootViewCreator:self.creator];
76
 	return [[RNNRootViewController alloc] initWithNode:node rootViewCreator:self.creator];
80
 }
77
 }
81
 
78
 
82
-- (UINavigationController*)createContainerStack:(RNNLayoutNode*)node
83
-{
79
+- (UINavigationController*)createContainerStack:(RNNLayoutNode*)node {
84
 	UINavigationController* vc = [[UINavigationController alloc] init];
80
 	UINavigationController* vc = [[UINavigationController alloc] init];
85
 	
81
 	
86
 	NSMutableArray* controllers = [NSMutableArray new];
82
 	NSMutableArray* controllers = [NSMutableArray new];
92
 	return vc;
88
 	return vc;
93
 }
89
 }
94
 
90
 
95
--(UITabBarController*)createTabs:(RNNLayoutNode*)node
96
-{
91
+-(UITabBarController*)createTabs:(RNNLayoutNode*)node {
97
 	UITabBarController* vc = [[UITabBarController alloc] init];
92
 	UITabBarController* vc = [[UITabBarController alloc] init];
98
 	
93
 	
99
 	NSMutableArray* controllers = [NSMutableArray new];
94
 	NSMutableArray* controllers = [NSMutableArray new];
109
 	return vc;
104
 	return vc;
110
 }
105
 }
111
 
106
 
112
-- (UIViewController*)createSideMenu:(RNNLayoutNode*)node
113
-{
107
+- (UIViewController*)createSideMenu:(RNNLayoutNode*)node {
114
 	NSMutableArray* childrenVCs = [NSMutableArray new];
108
 	NSMutableArray* childrenVCs = [NSMutableArray new];
115
 	
109
 	
116
 	
110
 	

+ 1
- 0
ios/RNNStore.h View File

6
 @interface RNNStore : NSObject
6
 @interface RNNStore : NSObject
7
 
7
 
8
 @property NSMutableArray *modalsToDismissArray;
8
 @property NSMutableArray *modalsToDismissArray;
9
+@property BOOL isReadyToReceiveCommands;
9
 
10
 
10
 - (UIViewController*)findContainerForId:(NSString*)containerId;
11
 - (UIViewController*)findContainerForId:(NSString*)containerId;
11
 - (void)setContainer:(UIViewController*)viewController containerId:(NSString*)containerId;
12
 - (void)setContainer:(UIViewController*)viewController containerId:(NSString*)containerId;

+ 0
- 1
ios/RNNStore.m View File

5
 
5
 
6
 @property NSMapTable *containerStore;
6
 @property NSMapTable *containerStore;
7
 
7
 
8
-
9
 @end
8
 @end
10
 
9
 
11
 @implementation RNNStore
10
 @implementation RNNStore

+ 2
- 4
ios/ReactNativeNavigation.m View File

5
 
5
 
6
 @implementation ReactNativeNavigation
6
 @implementation ReactNativeNavigation
7
 
7
 
8
-+(void)bootstrap:(NSURL *)jsCodeLocation
9
-{
8
++(void)bootstrap:(NSURL *)jsCodeLocation {
10
 	[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:nil];
9
 	[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:nil];
11
 }
10
 }
12
 
11
 
13
-+(void)bootstrap:(NSURL *)jsCodeLocation launchOptions:(NSDictionary *)launchOptions
14
-{	
12
++(void)bootstrap:(NSURL *)jsCodeLocation launchOptions:(NSDictionary *)launchOptions {
15
 	[[RNN instance] bootstrap:jsCodeLocation launchOptions:launchOptions];
13
 	[[RNN instance] bootstrap:jsCodeLocation launchOptions:launchOptions];
16
 }
14
 }
17
 
15
 

+ 1
- 1
playground/scripts/unit.ios.js View File

9
             test
9
             test
10
             -scheme "playground"
10
             -scheme "playground"
11
             -project playground.xcodeproj
11
             -project playground.xcodeproj
12
-            -destination 'platform=iOS Simulator,name=iPhone SE'
12
+            -destination 'platform=iOS Simulator,name=iPhone 7'
13
             `;
13
             `;
14
 
14
 
15
   // if (hasXcpretty()) {
15
   // if (hasXcpretty()) {