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,7 +8,6 @@
8 8
 
9 9
 @interface RNN : NSObject
10 10
 
11
-@property (readonly) BOOL isReadyToReceiveCommands;
12 11
 @property (readonly) RCTBridge* bridge;
13 12
 @property (readonly) RNNEventEmitter* eventEmitter;
14 13
 @property (readonly) RNNStore *store;

+ 30
- 17
ios/RNN.m View File

@@ -5,10 +5,13 @@
5 5
 #import <React/RCTBridge.h>
6 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 14
 @property (readwrite) RCTBridge* bridge;
11
-@property (readwrite) BOOL isReadyToReceiveCommands;
12 15
 @property (readwrite) RNNEventEmitter* eventEmitter;
13 16
 
14 17
 @property (readwrite) RNNStore *store;
@@ -36,8 +39,8 @@
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 44
 	self.eventEmitter = [RNNEventEmitter new];
42 45
 	
43 46
 	UIApplication.sharedApplication.delegate.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
@@ -46,34 +49,44 @@
46 49
 	[RNNSplashScreen show];
47 50
 	
48 51
 	[self registerForJsEvents];
52
+	
49 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 81
 	self.store = [RNNStore new];
74 82
 	[self resetRootViewControllerOnlyOnJSDevReload];
75 83
 }
76 84
 
85
+-(void)onJavaScriptLoaded {
86
+	self.store.isReadyToReceiveCommands = true;
87
+	[self.eventEmitter sendOnAppLaunched];
88
+}
89
+
77 90
 -(void)resetRootViewControllerOnlyOnJSDevReload {
78 91
 	if(![UIApplication.sharedApplication.delegate.window.rootViewController isKindOfClass:[RNNSplashScreen class]]) {
79 92
 		UIApplication.sharedApplication.delegate.window.rootViewController = nil;

+ 4
- 0
ios/RNNBridgeModule.h View File

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

+ 15
- 7
ios/RNNBridgeModule.m View File

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

+ 6
- 2
ios/RNNCommandsHandler.h View File

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

+ 34
- 21
ios/RNNCommandsHandler.m View File

@@ -1,22 +1,28 @@
1 1
 
2 2
 #import "RNNCommandsHandler.h"
3 3
 
4
-
5
-#import "RNN.h"
6
-#import "RNNControllerFactory.h"
7
-#import "RNNReactRootViewCreator.h"
8
-#import "RNNStore.h"
9 4
 #import "RNNModalManager.h"
10 5
 #import "RNNNavigationStackManager.h"
11 6
 
7
+@interface RNNCommandsHandler ()
8
+@property RNNControllerFactory *controllerFactory;
9
+@property RNNStore *store;
10
+@end
11
+
12 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 21
 #pragma mark - public
15 22
 
16 23
 -(void) setRoot:(NSDictionary*)layout {
17 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 27
 	UIApplication.sharedApplication.delegate.window.rootViewController = vc;
22 28
 	[UIApplication.sharedApplication.delegate.window makeKeyAndVisible];
@@ -24,41 +30,48 @@
24 30
 
25 31
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout {
26 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 43
 -(void) pop:(NSString*)containerId {
35 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 54
 -(void) showModal:(NSDictionary*)layout {
42 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 61
 -(void) dismissModal:(NSString*)containerId {
49 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 66
 -(void) dismissAllModals {
54 67
 	[self assertReady];
55
-	[[[RNNModalManager alloc] initWithStore:[RNN instance].store] dismissAllModals];
68
+	[[[RNNModalManager alloc] initWithStore:self.store] dismissAllModals];
56 69
 }
57 70
 
58 71
 #pragma mark - private
59 72
 
60
-- (void)assertReady {
61
-	if (![RNN instance].isReadyToReceiveCommands) {
73
+-(void) assertReady {
74
+	if (!self.store.isReadyToReceiveCommands) {
62 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,15 +25,13 @@
25 25
 	return self;
26 26
 }
27 27
 
28
-- (UIViewController*)createLayoutAndSaveToStore:(NSDictionary*)layout
29
-{
28
+- (UIViewController*)createLayoutAndSaveToStore:(NSDictionary*)layout {
30 29
 	return [self fromTree:layout];
31 30
 }
32 31
 
33 32
 # pragma mark private
34 33
 
35
-- (UIViewController*)fromTree:(NSDictionary*)json
36
-{
34
+- (UIViewController*)fromTree:(NSDictionary*)json {
37 35
 	RNNLayoutNode* node = [RNNLayoutNode create:json];
38 36
 	
39 37
 	UIViewController* result;
@@ -74,13 +72,11 @@
74 72
 	return result;
75 73
 }
76 74
 
77
-- (RNNRootViewController*)createContainer:(RNNLayoutNode*)node
78
-{
75
+- (RNNRootViewController*)createContainer:(RNNLayoutNode*)node {
79 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 80
 	UINavigationController* vc = [[UINavigationController alloc] init];
85 81
 	
86 82
 	NSMutableArray* controllers = [NSMutableArray new];
@@ -92,8 +88,7 @@
92 88
 	return vc;
93 89
 }
94 90
 
95
--(UITabBarController*)createTabs:(RNNLayoutNode*)node
96
-{
91
+-(UITabBarController*)createTabs:(RNNLayoutNode*)node {
97 92
 	UITabBarController* vc = [[UITabBarController alloc] init];
98 93
 	
99 94
 	NSMutableArray* controllers = [NSMutableArray new];
@@ -109,8 +104,7 @@
109 104
 	return vc;
110 105
 }
111 106
 
112
-- (UIViewController*)createSideMenu:(RNNLayoutNode*)node
113
-{
107
+- (UIViewController*)createSideMenu:(RNNLayoutNode*)node {
114 108
 	NSMutableArray* childrenVCs = [NSMutableArray new];
115 109
 	
116 110
 	

+ 1
- 0
ios/RNNStore.h View File

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

+ 0
- 1
ios/RNNStore.m View File

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

+ 2
- 4
ios/ReactNativeNavigation.m View File

@@ -5,13 +5,11 @@
5 5
 
6 6
 @implementation ReactNativeNavigation
7 7
 
8
-+(void)bootstrap:(NSURL *)jsCodeLocation
9
-{
8
++(void)bootstrap:(NSURL *)jsCodeLocation {
10 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 13
 	[[RNN instance] bootstrap:jsCodeLocation launchOptions:launchOptions];
16 14
 }
17 15
 

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

@@ -9,7 +9,7 @@ function testProject() {
9 9
             test
10 10
             -scheme "playground"
11 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 15
   // if (hasXcpretty()) {