Browse Source

Detached options from presenters, design improvments for LayoutProtocol (#4049)

* Detached options from presenters, design improvments for LayoutProtocol

* fixes topBar.background.clipToBounds

* Fixes e2e

* Fixes unit tests

* Homogeneous constructors for parent and child view controllers

* Handle parent options merging with children in optionsResolver

* Fix topBar.background.clipToBounds

* Removed unnecessary options merging

* Fixes shared element transition

* Fixed sideMenu inside bottomTabs
Yogev Ben David 6 years ago
parent
commit
f7a0e5679d
No account linked to committer's email address
38 changed files with 455 additions and 471 deletions
  1. 1
    1
      e2e/ComplexLayout.test.js
  2. 6
    0
      lib/ios/RNNBackgroundOptions.m
  3. 2
    18
      lib/ios/RNNBasePresenter.h
  4. 3
    22
      lib/ios/RNNBasePresenter.m
  5. 30
    26
      lib/ios/RNNCommandsHandler.m
  6. 55
    71
      lib/ios/RNNControllerFactory.m
  7. 3
    0
      lib/ios/RNNLayoutProtocol.h
  8. 3
    1
      lib/ios/RNNLeafProtocol.h
  9. 2
    2
      lib/ios/RNNModalManager.m
  10. 3
    0
      lib/ios/RNNNavigationController.h
  11. 25
    17
      lib/ios/RNNNavigationController.m
  12. 2
    1
      lib/ios/RNNNavigationControllerPresenter.m
  13. 0
    2
      lib/ios/RNNNavigationOptions.h
  14. 0
    8
      lib/ios/RNNNavigationOptions.m
  15. 8
    0
      lib/ios/RNNParentOptionsResolver.h
  16. 9
    0
      lib/ios/RNNParentOptionsResolver.m
  17. 5
    2
      lib/ios/RNNParentProtocol.h
  18. 13
    6
      lib/ios/RNNRootViewController.h
  19. 58
    59
      lib/ios/RNNRootViewController.m
  20. 0
    19
      lib/ios/RNNSideMenu/MMDrawerController/MMDrawerController.m
  21. 3
    9
      lib/ios/RNNSideMenuChildVC.h
  22. 28
    30
      lib/ios/RNNSideMenuChildVC.m
  23. 2
    2
      lib/ios/RNNSideMenuController.h
  24. 18
    23
      lib/ios/RNNSideMenuController.m
  25. 15
    2
      lib/ios/RNNSideMenuSideOptions.m
  26. 3
    10
      lib/ios/RNNSplitViewController.h
  27. 20
    19
      lib/ios/RNNSplitViewController.m
  28. 3
    1
      lib/ios/RNNTabBarController.h
  29. 36
    15
      lib/ios/RNNTabBarController.m
  30. 2
    6
      lib/ios/RNNTabBarPresenter.m
  31. 3
    0
      lib/ios/RNNTopTabsViewController.h
  32. 23
    15
      lib/ios/RNNTopTabsViewController.m
  33. 0
    2
      lib/ios/RNNViewControllerPresenter.h
  34. 2
    6
      lib/ios/RNNViewControllerPresenter.m
  35. 8
    0
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  36. 7
    5
      lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m
  37. 46
    7
      lib/ios/ReactNativeNavigationTests/RNNNavigationControllerTest.m
  38. 8
    64
      lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m

+ 1
- 1
e2e/ComplexLayout.test.js View File

20
     await expect(elementByLabel('External component in deep stack')).toBeVisible();
20
     await expect(elementByLabel('External component in deep stack')).toBeVisible();
21
   });
21
   });
22
 
22
 
23
-  test(':android: merge options correctly in SideMenu inside BottomTabs layout', async () => {
23
+  test('merge options correctly in SideMenu inside BottomTabs layout', async () => {
24
     await elementById(testIDs.COMPLEX_LAYOUT_BUTTON).tap();
24
     await elementById(testIDs.COMPLEX_LAYOUT_BUTTON).tap();
25
     await elementById(testIDs.SIDE_MENU_LAYOUT_INSIDE_BOTTOM_TAB).tap();
25
     await elementById(testIDs.SIDE_MENU_LAYOUT_INSIDE_BOTTOM_TAB).tap();
26
     await elementById(testIDs.SECOND_TAB_BAR_BUTTON).tap();
26
     await elementById(testIDs.SECOND_TAB_BAR_BUTTON).tap();

+ 6
- 0
lib/ios/RNNBackgroundOptions.m View File

76
 			self.originalTopBarImages = nil;
76
 			self.originalTopBarImages = nil;
77
 		}
77
 		}
78
 	}
78
 	}
79
+
80
+	if (self.clipToBounds) {
81
+		navigationController.navigationBar.clipsToBounds = [self.clipToBounds boolValue];
82
+	} else {
83
+		navigationController.navigationBar.clipsToBounds = NO;
84
+	}
79
 }
85
 }
80
 
86
 
81
 - (void)storeOriginalTopBarImages:(UINavigationController *)navigationController {
87
 - (void)storeOriginalTopBarImages:(UINavigationController *)navigationController {

+ 2
- 18
lib/ios/RNNBasePresenter.h View File

1
 #import <Foundation/Foundation.h>
1
 #import <Foundation/Foundation.h>
2
 #import "RNNNavigationOptions.h"
2
 #import "RNNNavigationOptions.h"
3
 
3
 
4
-@protocol RNNPresenterDelegate <NSObject>
5
-
6
-- (void)optionsUpdated;
7
-
8
-@end
9
-
10
 @interface RNNBasePresenter : NSObject
4
 @interface RNNBasePresenter : NSObject
11
 
5
 
12
-@property (nonatomic, weak) id<RNNPresenterDelegate> delegate;
13
-@property (nonatomic, strong) RNNNavigationOptions* options;
14
-
15
-- (instancetype)initWithOptions:(RNNNavigationOptions *)options;
16
-
17
-- (RNNNavigationOptions *)presentWithChildOptions:(RNNNavigationOptions *)childOptions on:(UIViewController *)viewController;
18
-
19
-- (void)present:(RNNNavigationOptions *)options on:(UIViewController *)viewController;
20
-
21
-- (void)presentOn:(UIViewController *)viewController;
22
-
23
-- (void)overrideOptions:(RNNNavigationOptions *)options;
6
+- (void)present:(RNNNavigationOptions *)options onViewControllerDidLoad:(UIViewController *)viewController;
7
+- (void)present:(RNNNavigationOptions *)options onViewControllerWillAppear:(UIViewController *)viewController;
24
 
8
 
25
 @end
9
 @end

+ 3
- 22
lib/ios/RNNBasePresenter.m View File

2
 
2
 
3
 @implementation RNNBasePresenter
3
 @implementation RNNBasePresenter
4
 
4
 
5
-- (instancetype)initWithOptions:(RNNNavigationOptions *)options {
6
-	self = [super init];
7
-	if (self) {
8
-		self.options = options;
9
-	}
10
-	return self;
11
-}
12
-
13
-- (void)presentOn:(UIViewController *)viewController {
14
-	[self.options applyOn:viewController];
15
-}
16
-
17
-- (void)present:(RNNNavigationOptions *)options on:(UIViewController *)viewController {
5
+- (void)present:(RNNNavigationOptions *)options onViewControllerWillAppear:(UIViewController *)viewController {
18
 	[options applyOn:viewController];
6
 	[options applyOn:viewController];
19
 }
7
 }
20
 
8
 
21
-- (RNNNavigationOptions *)presentWithChildOptions:(RNNNavigationOptions *)childOptions on:(UIViewController *)viewController {
22
-	RNNNavigationOptions* options = [self.options combineWithOptions:childOptions];
23
-	[self present:options on:viewController];
24
-	
25
-	return options;
26
-}
27
-
28
-- (void)overrideOptions:(RNNNavigationOptions *)options {
29
-	[_options mergeOptions:options overrideOptions:YES];
9
+- (void)present:(RNNNavigationOptions *)options onViewControllerDidLoad:(UIViewController *)viewController {
10
+	[options applyOn:viewController];
30
 }
11
 }
31
 
12
 
32
 @end
13
 @end

+ 30
- 26
lib/ios/RNNCommandsHandler.m View File

73
 	[CATransaction begin];
73
 	[CATransaction begin];
74
 	[CATransaction setCompletionBlock:completion];
74
 	[CATransaction setCompletionBlock:completion];
75
 	
75
 	
76
-	[vc.presenter overrideOptions:options];
77
-	[vc.presenter presentOn:vc];
78
-	
76
+	while (vc != nil) {
77
+		if ([vc conformsToProtocol:@protocol(RNNLayoutProtocol)]) {
78
+			[vc mergeOptions:options];
79
+		}
80
+		vc = (UIViewController<RNNLayoutProtocol>*)vc.parentViewController;
81
+	}
82
+
79
 	[CATransaction commit];
83
 	[CATransaction commit];
80
 }
84
 }
81
 
85
 
90
 	RNNRootViewController *newVc = (RNNRootViewController *)[_controllerFactory createLayoutAndSaveToStore:layout];
94
 	RNNRootViewController *newVc = (RNNRootViewController *)[_controllerFactory createLayoutAndSaveToStore:layout];
91
 	UIViewController *fromVC = [_store findComponentForId:componentId];
95
 	UIViewController *fromVC = [_store findComponentForId:componentId];
92
 	
96
 	
93
-	if ([newVc.presenter.options.preview.reactTag floatValue] > 0) {
97
+	if ([newVc.options.preview.reactTag floatValue] > 0) {
94
 		UIViewController* vc = [_store findComponentForId:componentId];
98
 		UIViewController* vc = [_store findComponentForId:componentId];
95
 		
99
 		
96
 		if([vc isKindOfClass:[RNNRootViewController class]]) {
100
 		if([vc isKindOfClass:[RNNRootViewController class]]) {
100
       rootVc.previewCallback = ^(UIViewController *vcc) {
104
       rootVc.previewCallback = ^(UIViewController *vcc) {
101
 				RNNRootViewController* rvc  = (RNNRootViewController*)vcc;
105
 				RNNRootViewController* rvc  = (RNNRootViewController*)vcc;
102
 				[self->_eventEmitter sendOnPreviewCompleted:componentId previewComponentId:newVc.layoutInfo.componentId];
106
 				[self->_eventEmitter sendOnPreviewCompleted:componentId previewComponentId:newVc.layoutInfo.componentId];
103
-				if ([newVc.presenter.options.preview.commit floatValue] > 0) {
107
+				if ([newVc.options.preview.commit floatValue] > 0) {
104
 					[CATransaction begin];
108
 					[CATransaction begin];
105
 					[CATransaction setCompletionBlock:^{
109
 					[CATransaction setCompletionBlock:^{
106
 						[self->_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
110
 						[self->_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
113
 			
117
 			
114
 			CGSize size = CGSizeMake(rootVc.view.frame.size.width, rootVc.view.frame.size.height);
118
 			CGSize size = CGSizeMake(rootVc.view.frame.size.width, rootVc.view.frame.size.height);
115
 			
119
 			
116
-			if (newVc.presenter.options.preview.width) {
117
-				size.width = [newVc.presenter.options.preview.width floatValue];
120
+			if (newVc.options.preview.width) {
121
+				size.width = [newVc.options.preview.width floatValue];
118
 			}
122
 			}
119
 			
123
 			
120
-			if (newVc.presenter.options.preview.height) {
121
-				size.height = [newVc.presenter.options.preview.height floatValue];
124
+			if (newVc.options.preview.height) {
125
+				size.height = [newVc.options.preview.height floatValue];
122
 			}
126
 			}
123
 			
127
 			
124
-			if (newVc.presenter.options.preview.width || newVc.presenter.options.preview.height) {
128
+			if (newVc.options.preview.width || newVc.options.preview.height) {
125
 				newVc.preferredContentSize = size;
129
 				newVc.preferredContentSize = size;
126
 			}
130
 			}
127
       
131
       
128
 			RCTExecuteOnMainQueue(^{
132
 			RCTExecuteOnMainQueue(^{
129
-				UIView *view = [[ReactNativeNavigation getBridge].uiManager viewForReactTag:newVc.presenter.options.preview.reactTag];
133
+				UIView *view = [[ReactNativeNavigation getBridge].uiManager viewForReactTag:newVc.options.preview.reactTag];
130
 				[rootVc registerForPreviewingWithDelegate:(id)rootVc sourceView:view];
134
 				[rootVc registerForPreviewingWithDelegate:(id)rootVc sourceView:view];
131
 			});
135
 			});
132
 		}
136
 		}
133
 	} else {
137
 	} else {
134
-		id animationDelegate = (newVc.presenter.options.animations.push.hasCustomAnimation || newVc.isCustomTransitioned) ? newVc : nil;
135
-		[newVc waitForReactViewRender:(newVc.presenter.options.animations.push.waitForRender || animationDelegate) perform:^{
136
-			[_stackManager push:newVc onTop:fromVC animated:newVc.presenter.options.animations.push.enable animationDelegate:animationDelegate completion:^{
138
+		id animationDelegate = (newVc.options.animations.push.hasCustomAnimation || newVc.isCustomTransitioned) ? newVc : nil;
139
+		[newVc waitForReactViewRender:(newVc.options.animations.push.waitForRender || animationDelegate) perform:^{
140
+			[_stackManager push:newVc onTop:fromVC animated:newVc.options.animations.push.enable animationDelegate:animationDelegate completion:^{
137
 				[_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
141
 				[_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
138
 				completion();
142
 				completion();
139
 			} rejection:rejection];
143
 			} rejection:rejection];
145
 	[self assertReady];
149
 	[self assertReady];
146
 	
150
 	
147
 	UIViewController<RNNParentProtocol> *newVC = [_controllerFactory createLayoutAndSaveToStore:layout];
151
 	UIViewController<RNNParentProtocol> *newVC = [_controllerFactory createLayoutAndSaveToStore:layout];
148
-	RNNNavigationOptions* options = [newVC getLeafViewController].presenter.options;
152
+	RNNNavigationOptions* options = [newVC getLeafViewController].options;
149
 	UIViewController *fromVC = [_store findComponentForId:componentId];
153
 	UIViewController *fromVC = [_store findComponentForId:componentId];
150
 	__weak typeof(RNNEventEmitter*) weakEventEmitter = _eventEmitter;
154
 	__weak typeof(RNNEventEmitter*) weakEventEmitter = _eventEmitter;
151
 	[_stackManager setStackRoot:newVC fromViewController:fromVC animated:options.animations.setStackRoot.enable completion:^{
155
 	[_stackManager setStackRoot:newVC fromViewController:fromVC animated:options.animations.setStackRoot.enable completion:^{
158
 	[self assertReady];
162
 	[self assertReady];
159
 	
163
 	
160
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
164
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
161
-	[vc.presenter.options mergeWith:options];
165
+	[vc.options mergeWith:options];
162
 	
166
 	
163
 	UINavigationController *nvc = vc.navigationController;
167
 	UINavigationController *nvc = vc.navigationController;
164
 	
168
 	
165
 	if ([nvc topViewController] == vc) {
169
 	if ([nvc topViewController] == vc) {
166
-		if (vc.presenter.options.animations.pop) {
170
+		if (vc.options.animations.pop) {
167
 			nvc.delegate = vc;
171
 			nvc.delegate = vc;
168
 		} else {
172
 		} else {
169
 			nvc.delegate = nil;
173
 			nvc.delegate = nil;
171
 	} else {
175
 	} else {
172
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
176
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
173
 		[vcs removeObject:vc];
177
 		[vcs removeObject:vc];
174
-		[nvc setViewControllers:vcs animated:vc.presenter.options.animations.pop.enable];
178
+		[nvc setViewControllers:vcs animated:vc.options.animations.pop.enable];
175
 	}
179
 	}
176
 	
180
 	
177
-	[_stackManager pop:vc animated:vc.presenter.options.animations.pop.enable completion:^{
181
+	[_stackManager pop:vc animated:vc.options.animations.pop.enable completion:^{
178
 		[_store removeComponent:componentId];
182
 		[_store removeComponent:componentId];
179
 		[_eventEmitter sendOnNavigationCommandCompletion:pop params:@{@"componentId": componentId}];
183
 		[_eventEmitter sendOnNavigationCommandCompletion:pop params:@{@"componentId": componentId}];
180
 		completion();
184
 		completion();
186
 - (void)popTo:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
190
 - (void)popTo:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
187
 	[self assertReady];
191
 	[self assertReady];
188
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
192
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
189
-	[vc.presenter.options mergeWith:options];
193
+	[vc.options mergeWith:options];
190
 	
194
 	
191
-	[_stackManager popTo:vc animated:vc.presenter.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
195
+	[_stackManager popTo:vc animated:vc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
192
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
196
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
193
 		[self removePopedViewControllers:poppedViewControllers];
197
 		[self removePopedViewControllers:poppedViewControllers];
194
 		completion();
198
 		completion();
198
 - (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
202
 - (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary *)options completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
199
 	[self assertReady];
203
 	[self assertReady];
200
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
204
 	RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
201
-	[vc.presenter.options mergeWith:options];
205
+	[vc.options mergeWith:options];
202
 	
206
 	
203
 	[CATransaction begin];
207
 	[CATransaction begin];
204
 	[CATransaction setCompletionBlock:^{
208
 	[CATransaction setCompletionBlock:^{
206
 		completion();
210
 		completion();
207
 	}];
211
 	}];
208
 	
212
 	
209
-	[_stackManager popToRoot:vc animated:vc.presenter.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
213
+	[_stackManager popToRoot:vc animated:vc.options.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
210
 		[self removePopedViewControllers:poppedViewControllers];
214
 		[self removePopedViewControllers:poppedViewControllers];
211
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
215
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
212
 		
216
 		
220
 	
224
 	
221
 	UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
225
 	UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
222
 	
226
 	
223
-	[newVc.getLeafViewController waitForReactViewRender:newVc.getLeafViewController.presenter.options.animations.showModal.waitForRender perform:^{
224
-		[_modalManager showModal:newVc animated:newVc.getLeafViewController.presenter.options.animations.showModal.enable hasCustomAnimation:newVc.getLeafViewController.presenter.options.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
227
+	[newVc.getLeafViewController waitForReactViewRender:newVc.getLeafViewController.options.animations.showModal.waitForRender perform:^{
228
+		[_modalManager showModal:newVc animated:newVc.getLeafViewController.options.animations.showModal.enable hasCustomAnimation:newVc.getLeafViewController.options.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
225
 			[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
229
 			[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
226
 			completion(componentId);
230
 			completion(componentId);
227
 		}];
231
 		}];
236
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissModal params:@{@"componentId": componentId}];
240
 		[_eventEmitter sendOnNavigationCommandCompletion:dismissModal params:@{@"componentId": componentId}];
237
 	}];
241
 	}];
238
 	UIViewController<RNNParentProtocol> *modalToDismiss = (UIViewController<RNNParentProtocol>*)[_store findComponentForId:componentId];
242
 	UIViewController<RNNParentProtocol> *modalToDismiss = (UIViewController<RNNParentProtocol>*)[_store findComponentForId:componentId];
239
-	[modalToDismiss.getLeafViewController.presenter.options mergeWith:options];
243
+	[modalToDismiss.getLeafViewController.options mergeWith:options];
240
 	
244
 	
241
 	[self removePopedViewControllers:modalToDismiss.navigationController.viewControllers];
245
 	[self removePopedViewControllers:modalToDismiss.navigationController.viewControllers];
242
 	
246
 	

+ 55
- 71
lib/ios/RNNControllerFactory.m View File

100
 
100
 
101
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
101
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
102
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
102
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
103
-	
104
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
103
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
105
 	
104
 	
106
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithOptions:options];
107
-	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter isExternalComponent:NO presenter:presenter];
108
-
109
-	if (!component.isCustomViewController) {
105
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
106
+	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options];
107
+	
108
+	if (!component.isExternalViewController) {
110
 		CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
109
 		CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
111
 		[_bridge.uiManager setAvailableSize:availableSize forRootView:component.view];
110
 		[_bridge.uiManager setAvailableSize:availableSize forRootView:component.view];
112
 	}
111
 	}
112
+	
113
 	return (UIViewController<RNNParentProtocol> *)component;
113
 	return (UIViewController<RNNParentProtocol> *)component;
114
 }
114
 }
115
 
115
 
116
 - (UIViewController<RNNParentProtocol> *)createExternalComponent:(RNNLayoutNode*)node {
116
 - (UIViewController<RNNParentProtocol> *)createExternalComponent:(RNNLayoutNode*)node {
117
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
117
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
118
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
118
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
119
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
119
 
120
 
120
 	UIViewController* externalVC = [_store getExternalComponent:layoutInfo bridge:_bridge];
121
 	UIViewController* externalVC = [_store getExternalComponent:layoutInfo bridge:_bridge];
121
 	
122
 	
122
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithOptions:options];
123
-	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter isExternalComponent:YES presenter:presenter];
124
-	
125
-	[component addChildViewController:externalVC];
126
-	[component.view addSubview:externalVC.view];
127
-	[externalVC didMoveToParentViewController:component];
123
+	RNNRootViewController* component = [[RNNRootViewController alloc] initExternalComponentWithLayoutInfo:layoutInfo eventEmitter:_eventEmitter presenter:presenter options:options];
124
+	[component bindViewController:externalVC];
128
 	
125
 	
129
 	return (UIViewController<RNNParentProtocol> *)component;
126
 	return (UIViewController<RNNParentProtocol> *)component;
130
 }
127
 }
131
 
128
 
132
 
129
 
133
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
130
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
134
-	RNNNavigationController* vc = [[RNNNavigationController alloc] init];
131
+	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] init];
132
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
135
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
133
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
136
-
137
-	vc.presenter = [[RNNNavigationControllerPresenter alloc] initWithOptions:options];
138
-	vc.layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
134
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
139
 	
135
 	
140
-	NSMutableArray* controllers = [NSMutableArray new];
141
-	for (NSDictionary* child in node.children) {
142
-		[controllers addObject:[self fromTree:child]];
143
-	}
136
+	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
144
 	
137
 	
145
-	[vc setViewControllers:controllers];
138
+	RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
146
 	
139
 	
147
-	return vc;
140
+	return stack;
148
 }
141
 }
149
 
142
 
150
 -(UIViewController<RNNParentProtocol> *)createTabs:(RNNLayoutNode*)node {
143
 -(UIViewController<RNNParentProtocol> *)createTabs:(RNNLayoutNode*)node {
151
-	RNNTabBarController* vc = [[RNNTabBarController alloc] initWithEventEmitter:_eventEmitter];
152
-	vc.layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
144
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
153
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
145
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
154
-	vc.presenter = [[RNNTabBarPresenter alloc] initWithOptions:options];
146
+	RNNTabBarPresenter* presenter = [[RNNTabBarPresenter alloc] init];
147
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
148
+
149
+	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
155
 	
150
 	
156
-	NSMutableArray* controllers = [NSMutableArray new];
157
-	for (NSDictionary *child in node.children) {
158
-		UIViewController<RNNParentProtocol>* childVc = [self fromTree:child];
159
-		[controllers addObject:childVc];
160
-	}
161
-	[vc setViewControllers:controllers];
151
+	RNNTabBarController* tabsController = [[RNNTabBarController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter eventEmitter:_eventEmitter];
162
 	
152
 	
163
-	return vc;
153
+	return tabsController;
164
 }
154
 }
165
 
155
 
166
 - (UIViewController<RNNParentProtocol> *)createTopTabs:(RNNLayoutNode*)node {
156
 - (UIViewController<RNNParentProtocol> *)createTopTabs:(RNNLayoutNode*)node {
167
-	RNNTopTabsViewController* vc = [[RNNTopTabsViewController alloc] init];
168
-	vc.layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
169
-	
170
-	NSMutableArray* controllers = [NSMutableArray new];
171
-	for (NSDictionary *child in node.children) {
172
-		RNNRootViewController* childVc = (RNNRootViewController*)[self fromTree:child];
173
-		[controllers addObject:childVc];
174
-		[_bridge.uiManager setAvailableSize:vc.contentView.bounds.size forRootView:childVc.view];
175
-	}
157
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
158
+	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
159
+	RNNBasePresenter* presenter = [[RNNBasePresenter alloc] init];
160
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
161
+
162
+	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
176
 	
163
 	
177
-	[vc setViewControllers:controllers];
164
+	RNNTopTabsViewController* topTabsController = [[RNNTopTabsViewController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
178
 	
165
 	
179
-	return vc;
166
+	return topTabsController;
180
 }
167
 }
181
 
168
 
182
 - (UIViewController<RNNParentProtocol> *)createSideMenu:(RNNLayoutNode*)node {
169
 - (UIViewController<RNNParentProtocol> *)createSideMenu:(RNNLayoutNode*)node {
183
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
170
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
184
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
171
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
185
-	RNNBasePresenter* presenter = [[RNNBasePresenter alloc] initWithOptions:options];
186
-	
187
-	NSMutableArray* childrenVCs = [NSMutableArray new];
172
+	RNNBasePresenter* presenter = [[RNNBasePresenter alloc] init];
173
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
174
+
175
+	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
188
 	
176
 	
189
-	for (NSDictionary *child in node.children) {
190
-		UIViewController *vc = [self fromTree:child];
191
-		[childrenVCs addObject:vc];
192
-	}
193
-	RNNSideMenuController *sideMenu = [[RNNSideMenuController alloc] initWithControllers:childrenVCs presenter:presenter];
194
-	sideMenu.layoutInfo = layoutInfo;
177
+	RNNSideMenuController *sideMenu = [[RNNSideMenuController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
195
 	
178
 	
196
 	return sideMenu;
179
 	return sideMenu;
197
 }
180
 }
198
 
181
 
199
 
182
 
200
 - (UIViewController<RNNParentProtocol> *)createSideMenuChild:(RNNLayoutNode*)node type:(RNNSideMenuChildType)type {
183
 - (UIViewController<RNNParentProtocol> *)createSideMenuChild:(RNNLayoutNode*)node type:(RNNSideMenuChildType)type {
201
-	UIViewController<RNNParentProtocol>* child = [self fromTree:node.children[0]];
184
+	UIViewController<RNNParentProtocol>* childVc = [self fromTree:node.children[0]];
185
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
202
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
186
 	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
203
-	RNNSideMenuChildVC *sideMenuChild = [[RNNSideMenuChildVC alloc] initWithChild: child type:type];
204
-	sideMenuChild.presenter = [[RNNBasePresenter alloc] initWithOptions:options];
187
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
188
+
189
+	RNNSideMenuChildVC *sideMenuChild = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:layoutInfo childViewControllers:@[childVc] options:options optionsResolver:optionsResolver presenter:[[RNNBasePresenter alloc] init] type:type];
205
 	
190
 	
206
 	return sideMenuChild;
191
 	return sideMenuChild;
207
 }
192
 }
208
 
193
 
209
 - (UIViewController<RNNParentProtocol> *)createSplitView:(RNNLayoutNode*)node {
194
 - (UIViewController<RNNParentProtocol> *)createSplitView:(RNNLayoutNode*)node {
195
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
196
+	RNNNavigationOptions* options = [_optionsManager createOptions:node.data[@"options"]];
197
+	RNNBasePresenter* presenter = [[RNNBasePresenter alloc] init];
198
+	RNNParentOptionsResolver* optionsResolver = [[RNNParentOptionsResolver alloc] init];
210
 
199
 
211
-	NSString* componentId = node.nodeId;
212
-	
213
-	RNNSplitViewOptions* options = [[RNNSplitViewOptions alloc] initWithDict:_optionsManager.defaultOptionsDict];
214
-	[options mergeWith:node.data[@"options"]];
215
-
216
-	RNNSplitViewController* svc = [[RNNSplitViewController alloc] initWithOptions:options withComponentId:componentId rootViewCreator:_creator eventEmitter:_eventEmitter];
217
-
218
-	// We need two children of the node for successful Master / Detail
219
-	NSDictionary *master = node.children[0];
220
-	NSDictionary *detail = node.children[1];
200
+	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
221
 
201
 
222
-	// Create view controllers
223
-	RNNRootViewController* masterVc = (RNNRootViewController*)[self fromTree:master];
224
-	RNNRootViewController* detailVc = (RNNRootViewController*)[self fromTree:detail];
202
+	RNNSplitViewController* splitViewController = [[RNNSplitViewController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
225
 
203
 
226
-	// Set the controllers and delegate to masterVC
227
-	svc.viewControllers = [NSArray arrayWithObjects:masterVc, detailVc, nil];
228
-	svc.delegate = masterVc;
204
+	return splitViewController;
205
+}
229
 
206
 
230
-	return svc;
207
+- (NSArray<UIViewController *> *)extractChildrenViewControllersFromNode:(RNNLayoutNode *)node {
208
+	NSMutableArray* childrenArray = [NSMutableArray new];
209
+	for (NSDictionary* child in node.children) {
210
+		UIViewController* childVc = [self fromTree:child];
211
+		[childrenArray addObject:childVc];
212
+	}
213
+	
214
+	return childrenArray;
231
 }
215
 }
232
 
216
 
233
 @end
217
 @end

+ 3
- 0
lib/ios/RNNLayoutProtocol.h View File

7
 
7
 
8
 @property (nonatomic, retain) RNNBasePresenter* presenter;
8
 @property (nonatomic, retain) RNNBasePresenter* presenter;
9
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
9
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
10
+@property (nonatomic, strong) RNNNavigationOptions* options;
11
+
12
+- (void)mergeOptions:(RNNNavigationOptions *)options;
10
 
13
 
11
 @end
14
 @end

+ 3
- 1
lib/ios/RNNLeafProtocol.h View File

4
 
4
 
5
 @protocol RNNLeafProtocol <RNNLayoutProtocol>
5
 @protocol RNNLeafProtocol <RNNLayoutProtocol>
6
 
6
 
7
+- (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;
8
+
7
 - (UIViewController<RNNLeafProtocol> *)getLeafViewController;
9
 - (UIViewController<RNNLeafProtocol> *)getLeafViewController;
8
 
10
 
9
-- (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;
11
+- (void)bindViewController:(UIViewController *)viewController;
10
 
12
 
11
 @end
13
 @end

+ 2
- 2
lib/ios/RNNModalManager.m View File

60
 
60
 
61
 -(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
61
 -(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
62
 	UIViewController<RNNParentProtocol> *modalToDismiss = [_pendingModalIdsToDismiss lastObject];
62
 	UIViewController<RNNParentProtocol> *modalToDismiss = [_pendingModalIdsToDismiss lastObject];
63
-	RNNNavigationOptions* options = modalToDismiss.getLeafViewController.presenter.options;
63
+	RNNNavigationOptions* options = modalToDismiss.getLeafViewController.options;
64
 
64
 
65
 	if(!modalToDismiss) {
65
 	if(!modalToDismiss) {
66
 		return;
66
 		return;
88
 	} else {
88
 	} else {
89
 		[modalToDismiss.view removeFromSuperview];
89
 		[modalToDismiss.view removeFromSuperview];
90
 		modalToDismiss.view = nil;
90
 		modalToDismiss.view = nil;
91
-		modalToDismiss.getLeafViewController.presenter.options.animations.dismissModal.enable = NO;
91
+		modalToDismiss.getLeafViewController.options.animations.dismissModal.enable = NO;
92
 		[self dismissedModal:modalToDismiss];
92
 		[self dismissedModal:modalToDismiss];
93
 		
93
 		
94
 		if (completion) {
94
 		if (completion) {

+ 3
- 0
lib/ios/RNNNavigationController.h View File

1
 #import <UIKit/UIKit.h>
1
 #import <UIKit/UIKit.h>
2
 #import "RNNParentProtocol.h"
2
 #import "RNNParentProtocol.h"
3
 #import "RNNNavigationControllerPresenter.h"
3
 #import "RNNNavigationControllerPresenter.h"
4
+#import "RNNParentOptionsResolver.h"
4
 
5
 
5
 @interface RNNNavigationController : UINavigationController <RNNParentProtocol>
6
 @interface RNNNavigationController : UINavigationController <RNNParentProtocol>
6
 
7
 
7
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
8
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
8
 @property (nonatomic, retain) RNNNavigationControllerPresenter* presenter;
9
 @property (nonatomic, retain) RNNNavigationControllerPresenter* presenter;
10
+@property (nonatomic, strong) RNNNavigationOptions* options;
11
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
9
 
12
 
10
 @end
13
 @end

+ 25
- 17
lib/ios/RNNNavigationController.m View File

5
 
5
 
6
 @implementation RNNNavigationController
6
 @implementation RNNNavigationController
7
 
7
 
8
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNNavigationControllerPresenter *)presenter {
9
+	self = [super init];
10
+
11
+	self.presenter = presenter;
12
+	self.options = options;
13
+	self.optionsResolver = optionsResolver;
14
+	self.layoutInfo = layoutInfo;
15
+	
16
+	[self setViewControllers:childViewControllers];
17
+	
18
+	return self;
19
+}
20
+
8
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
21
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
9
 	return self.viewControllers.lastObject.supportedInterfaceOrientations;
22
 	return self.viewControllers.lastObject.supportedInterfaceOrientations;
10
 }
23
 }
26
 		UIViewController *controller = self.viewControllers[self.viewControllers.count - 2];
39
 		UIViewController *controller = self.viewControllers[self.viewControllers.count - 2];
27
 		if ([controller isKindOfClass:[RNNRootViewController class]]) {
40
 		if ([controller isKindOfClass:[RNNRootViewController class]]) {
28
 			RNNRootViewController *rnnController = (RNNRootViewController *)controller;
41
 			RNNRootViewController *rnnController = (RNNRootViewController *)controller;
29
-			[rnnController.presenter presentOn:rnnController];
42
+			[rnnController.presenter present:rnnController.options onViewControllerDidLoad:rnnController];
30
 		}
43
 		}
31
 	}
44
 	}
32
 	
45
 	
34
 }
47
 }
35
 
48
 
36
 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
49
 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
37
-	return [[RNNModalAnimation alloc] initWithScreenTransition:self.getLeafViewController.presenter.options.animations.showModal isDismiss:NO];
50
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.getLeafViewController.options.animations.showModal isDismiss:NO];
38
 }
51
 }
39
 
52
 
40
 - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
53
 - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
41
-	return [[RNNModalAnimation alloc] initWithScreenTransition:self.getLeafViewController.presenter.options.animations.dismissModal isDismiss:YES];
54
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.getLeafViewController.options.animations.dismissModal isDismiss:YES];
42
 }
55
 }
43
 
56
 
44
 - (UIViewController *)getLeafViewController {
57
 - (UIViewController *)getLeafViewController {
49
 	return self.topViewController;
62
 	return self.topViewController;
50
 }
63
 }
51
 
64
 
52
-- (void)willMoveToParentViewController:(UIViewController *)parent {
53
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
54
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:_presenter.options];
55
-	}
65
+- (void)viewDidLoad {
66
+	[super viewDidLoad];
67
+	[_presenter present:self.options onViewControllerDidLoad:self];
56
 }
68
 }
57
 
69
 
58
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
59
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
60
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
61
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
62
-	}
70
+- (void)willMoveToParentViewController:(UIViewController *)parent {
71
+	[_optionsResolver resolve:self with:self.childViewControllers];
72
+	[_presenter present:self.options onViewControllerDidLoad:self];
63
 }
73
 }
64
 
74
 
65
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
66
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
67
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
68
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
69
-	}
75
+- (void)mergeOptions:(RNNNavigationOptions *)options {
76
+	[self.presenter present:options onViewControllerWillAppear:self];
70
 }
77
 }
71
 
78
 
79
+
72
 @end
80
 @end

+ 2
- 1
lib/ios/RNNNavigationControllerPresenter.m View File

2
 
2
 
3
 @implementation RNNNavigationControllerPresenter
3
 @implementation RNNNavigationControllerPresenter
4
 
4
 
5
-- (void)present:(RNNOptions *)options on:(UINavigationController *)navigationController {
5
+- (void)present:(RNNNavigationOptions *)options onViewControllerDidLoad:(UINavigationController *)navigationController {
6
 	[options applyOnNavigationController:navigationController];
6
 	[options applyOnNavigationController:navigationController];
7
+
7
 }
8
 }
8
 
9
 
9
 @end
10
 @end

+ 0
- 2
lib/ios/RNNNavigationOptions.h View File

38
 @property (nonatomic, strong) NSString* modalPresentationStyle;
38
 @property (nonatomic, strong) NSString* modalPresentationStyle;
39
 @property (nonatomic, strong) NSString* modalTransitionStyle;
39
 @property (nonatomic, strong) NSString* modalTransitionStyle;
40
 
40
 
41
-- (RNNNavigationOptions *)combineWithOptions:(RNNOptions *)options;
42
-
43
 @end
41
 @end

+ 0
- 8
lib/ios/RNNNavigationOptions.m View File

10
 
10
 
11
 @implementation RNNNavigationOptions
11
 @implementation RNNNavigationOptions
12
 
12
 
13
-- (RNNNavigationOptions *)combineWithOptions:(RNNOptions *)options {
14
-	RNNNavigationOptions *navigationOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
15
-	[navigationOptions mergeOptions:self overrideOptions:YES];
16
-	[navigationOptions mergeOptions:options overrideOptions:YES];
17
-	
18
-	return navigationOptions;
19
-}
20
-
21
 - (void)applyOn:(UIViewController *)viewController {
13
 - (void)applyOn:(UIViewController *)viewController {
22
 	[self.topBar applyOn:viewController];
14
 	[self.topBar applyOn:viewController];
23
 	[self.bottomTabs applyOn:viewController];
15
 	[self.bottomTabs applyOn:viewController];

+ 8
- 0
lib/ios/RNNParentOptionsResolver.h View File

1
+#import <Foundation/Foundation.h>
2
+#import "RNNLayoutProtocol.h"
3
+
4
+@interface RNNParentOptionsResolver : NSObject
5
+
6
+- (void)resolve:(UIViewController<RNNLayoutProtocol> *)parent with:(NSArray<UIViewController<RNNLayoutProtocol> *> *)children;
7
+
8
+@end

+ 9
- 0
lib/ios/RNNParentOptionsResolver.m View File

1
+#import "RNNParentOptionsResolver.h"
2
+
3
+@implementation RNNParentOptionsResolver
4
+
5
+- (void)resolve:(UIViewController<RNNLayoutProtocol> *)parent with:(NSArray<UIViewController<RNNLayoutProtocol> *> *)children {
6
+	
7
+}
8
+
9
+@end

+ 5
- 2
lib/ios/RNNParentProtocol.h View File

1
 #import "RNNLayoutProtocol.h"
1
 #import "RNNLayoutProtocol.h"
2
 #import "RNNLeafProtocol.h"
2
 #import "RNNLeafProtocol.h"
3
+#import "RNNParentOptionsResolver.h"
3
 
4
 
4
 @protocol RNNParentProtocol <RNNLayoutProtocol, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
5
 @protocol RNNParentProtocol <RNNLayoutProtocol, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
5
 
6
 
6
 @required
7
 @required
7
 
8
 
9
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
10
+
11
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter;
12
+
8
 - (UIViewController<RNNLeafProtocol> *)getLeafViewController;
13
 - (UIViewController<RNNLeafProtocol> *)getLeafViewController;
9
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)options;
10
-- (void)performOnChildLoad:(RNNNavigationOptions *)options;
11
 
14
 
12
 @end
15
 @end

+ 13
- 6
lib/ios/RNNRootViewController.h View File

12
 
12
 
13
 typedef void (^PreviewCallback)(UIViewController *vc);
13
 typedef void (^PreviewCallback)(UIViewController *vc);
14
 
14
 
15
-@interface RNNRootViewController : UIViewController	<RNNLeafProtocol, UIViewControllerPreviewingDelegate, UISearchResultsUpdating, UISearchBarDelegate, UINavigationControllerDelegate, UISplitViewControllerDelegate, RNNPresenterDelegate>
15
+@interface RNNRootViewController : UIViewController	<RNNLeafProtocol, UIViewControllerPreviewingDelegate, UISearchResultsUpdating, UISearchBarDelegate, UINavigationControllerDelegate, UISplitViewControllerDelegate>
16
 
16
 
17
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
17
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
18
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
18
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
19
 @property (nonatomic, strong) RNNViewControllerPresenter* presenter;
19
 @property (nonatomic, strong) RNNViewControllerPresenter* presenter;
20
+@property (nonatomic, strong) RNNNavigationOptions* options;
21
+
20
 @property (nonatomic) id<RNNRootViewCreator> creator;
22
 @property (nonatomic) id<RNNRootViewCreator> creator;
21
 @property (nonatomic, strong) RNNAnimator* animator;
23
 @property (nonatomic, strong) RNNAnimator* animator;
22
 @property (nonatomic, strong) UIViewController* previewController;
24
 @property (nonatomic, strong) UIViewController* previewController;
23
 @property (nonatomic, copy) PreviewCallback previewCallback;
25
 @property (nonatomic, copy) PreviewCallback previewCallback;
24
 
26
 
25
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
27
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
26
-			 rootViewCreator:(id<RNNRootViewCreator>)creator
27
-				eventEmitter:(RNNEventEmitter*)eventEmitter
28
-		 isExternalComponent:(BOOL)isExternalComponent
29
-				   presenter:(RNNViewControllerPresenter *)presenter;
28
+				   rootViewCreator:(id<RNNRootViewCreator>)creator
29
+					  eventEmitter:(RNNEventEmitter*)eventEmitter
30
+						 presenter:(RNNViewControllerPresenter *)presenter
31
+						   options:(RNNNavigationOptions *)options;
32
+
33
+- (instancetype)initExternalComponentWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
34
+									   eventEmitter:(RNNEventEmitter*)eventEmitter
35
+										  presenter:(RNNViewControllerPresenter *)presenter
36
+											options:(RNNNavigationOptions *)options;
30
 
37
 
31
-- (BOOL)isCustomViewController;
38
+- (BOOL)isExternalViewController;
32
 - (BOOL)isCustomTransitioned;
39
 - (BOOL)isCustomTransitioned;
33
 
40
 
34
 -(void)onButtonPress:(RNNUIBarButtonItem *)barButtonItem;
41
 -(void)onButtonPress:(RNNUIBarButtonItem *)barButtonItem;

+ 58
- 59
lib/ios/RNNRootViewController.m View File

13
 	BOOL _isBeingPresented;
13
 	BOOL _isBeingPresented;
14
 }
14
 }
15
 
15
 
16
-@property (nonatomic) BOOL isExternalComponent;
17
 @property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
16
 @property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
18
 
17
 
19
 @end
18
 @end
22
 
21
 
23
 @synthesize previewCallback;
22
 @synthesize previewCallback;
24
 
23
 
25
-- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
26
-				   rootViewCreator:(id<RNNRootViewCreator>)creator
27
-					  eventEmitter:(RNNEventEmitter*)eventEmitter
28
-			   isExternalComponent:(BOOL)isExternalComponent
29
-						 presenter:(RNNViewControllerPresenter *)presenter {
24
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo rootViewCreator:(id<RNNRootViewCreator>)creator eventEmitter:(RNNEventEmitter *)eventEmitter presenter:(RNNViewControllerPresenter *)presenter options:(RNNNavigationOptions *)options {
30
 	self = [super init];
25
 	self = [super init];
31
 	self.eventEmitter = eventEmitter;
26
 	self.eventEmitter = eventEmitter;
32
 	self.creator = creator;
27
 	self.creator = creator;
33
-	self.isExternalComponent = isExternalComponent;
34
 	self.layoutInfo = layoutInfo;
28
 	self.layoutInfo = layoutInfo;
35
 	self.presenter = presenter;
29
 	self.presenter = presenter;
36
-	self.presenter.delegate = self;
30
+	self.options = options;
37
 	
31
 	
38
-	self.animator = [[RNNAnimator alloc] initWithTransitionOptions:self.presenter.options.customTransition];
32
+	self.animator = [[RNNAnimator alloc] initWithTransitionOptions:self.options.customTransition];
39
 	
33
 	
40
-	if (!self.isExternalComponent) {
34
+	if (self.creator) {
41
 		self.view = [creator createRootView:self.layoutInfo.name rootViewId:self.layoutInfo.componentId];
35
 		self.view = [creator createRootView:self.layoutInfo.name rootViewId:self.layoutInfo.componentId];
42
 		[[NSNotificationCenter defaultCenter] addObserver:self
36
 		[[NSNotificationCenter defaultCenter] addObserver:self
43
 												 selector:@selector(reactViewReady)
37
 												 selector:@selector(reactViewReady)
54
 	return self;
48
 	return self;
55
 }
49
 }
56
 
50
 
51
+- (instancetype)initExternalComponentWithLayoutInfo:(RNNLayoutInfo *)layoutInfo eventEmitter:(RNNEventEmitter *)eventEmitter presenter:(RNNViewControllerPresenter *)presenter options:(RNNNavigationOptions *)options {
52
+	self = [self initWithLayoutInfo:layoutInfo rootViewCreator:nil eventEmitter:eventEmitter presenter:presenter options:options];
53
+	return self;
54
+}
55
+
56
+- (void)bindViewController:(UIViewController *)viewController {
57
+	[self addChildViewController:viewController];
58
+	[self.view addSubview:viewController.view];
59
+	[viewController didMoveToParentViewController:self];
60
+}
61
+
57
 -(void)viewWillAppear:(BOOL)animated{
62
 -(void)viewWillAppear:(BOOL)animated{
58
 	[super viewWillAppear:animated];
63
 	[super viewWillAppear:animated];
59
 	_isBeingPresented = YES;
64
 	_isBeingPresented = YES;
60
-	[_presenter presentOn:self];
61
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
62
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:_presenter.options];
63
-	}
65
+	[_presenter present:self.options onViewControllerWillAppear:self];
66
+	[self initReactCustomViews];
64
 }
67
 }
65
 
68
 
66
 -(void)viewDidAppear:(BOOL)animated {
69
 -(void)viewDidAppear:(BOOL)animated {
79
 }
82
 }
80
 
83
 
81
 - (void)willMoveToParentViewController:(UIViewController *)parent {
84
 - (void)willMoveToParentViewController:(UIViewController *)parent {
82
-	[_presenter presentOn:self];
83
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
84
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:_presenter.options];
85
-	}
85
+	[_presenter present:self.options onViewControllerDidLoad:self];
86
+}
87
+
88
+- (void)mergeOptions:(RNNNavigationOptions *)options {
89
+	[self.options mergeOptions:options overrideOptions:YES];
90
+	[self.presenter present:self.options onViewControllerWillAppear:self];
91
+	[self initReactCustomViews];
86
 }
92
 }
87
 
93
 
88
 - (void)reactViewReady {
94
 - (void)reactViewReady {
96
 
102
 
97
 
103
 
98
 - (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
104
 - (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
99
-	if (wait && !_isExternalComponent) {
105
+	if (wait && !self.isExternalViewController) {
100
 		[self onReactViewReady:readyBlock];
106
 		[self onReactViewReady:readyBlock];
101
 	} else {
107
 	} else {
102
 		readyBlock();
108
 		readyBlock();
108
 }
114
 }
109
 
115
 
110
 - (void)onReactViewReady:(RNNReactViewReadyCompletionBlock)readyBlock {
116
 - (void)onReactViewReady:(RNNReactViewReadyCompletionBlock)readyBlock {
111
-	if (self.isCustomViewController) {
117
+	if (self.isExternalViewController) {
112
 		readyBlock();
118
 		readyBlock();
113
 	} else {
119
 	} else {
114
 		self.reactViewReadyBlock = readyBlock;
120
 		self.reactViewReadyBlock = readyBlock;
125
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
131
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
126
 }
132
 }
127
 
133
 
128
-- (void)optionsUpdated {
134
+- (void)initReactCustomViews {
129
 	[self setCustomNavigationTitleView];
135
 	[self setCustomNavigationTitleView];
130
 	[self setCustomNavigationBarView];
136
 	[self setCustomNavigationBarView];
131
 	[self setCustomNavigationComponentBackground];
137
 	[self setCustomNavigationComponentBackground];
133
 
139
 
134
 - (void)setCustomNavigationTitleView {
140
 - (void)setCustomNavigationTitleView {
135
 	if (!_customTitleView && _isBeingPresented) {
141
 	if (!_customTitleView && _isBeingPresented) {
136
-		if (self.presenter.options.topBar.title.component.name) {
137
-			_customTitleView = (RNNReactView*)[_creator createRootViewFromComponentOptions:self.presenter.options.topBar.title.component];
142
+		if (self.options.topBar.title.component.name) {
143
+			_customTitleView = (RNNReactView*)[_creator createRootViewFromComponentOptions:self.options.topBar.title.component];
138
 			_customTitleView.backgroundColor = UIColor.clearColor;
144
 			_customTitleView.backgroundColor = UIColor.clearColor;
139
-			[_customTitleView setAlignment:self.presenter.options.topBar.title.component.alignment];
140
-			BOOL isCenter = [self.presenter.options.topBar.title.component.alignment isEqualToString:@"center"];
145
+			[_customTitleView setAlignment:self.options.topBar.title.component.alignment];
146
+			BOOL isCenter = [self.options.topBar.title.component.alignment isEqualToString:@"center"];
141
 			__weak RNNReactView *weakTitleView = _customTitleView;
147
 			__weak RNNReactView *weakTitleView = _customTitleView;
142
 			CGRect frame = self.navigationController.navigationBar.bounds;
148
 			CGRect frame = self.navigationController.navigationBar.bounds;
143
 			[_customTitleView setFrame:frame];
149
 			[_customTitleView setFrame:frame];
161
 
167
 
162
 - (void)setCustomNavigationBarView {
168
 - (void)setCustomNavigationBarView {
163
 	if (!_customTopBar) {
169
 	if (!_customTopBar) {
164
-		if (self.presenter.options.topBar.component.name) {
165
-			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.presenter.options.topBar.component];
170
+		if (self.options.topBar.component.name) {
171
+			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.options.topBar.component];
166
 			
172
 			
167
 			_customTopBar = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
173
 			_customTopBar = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
168
 			reactView.backgroundColor = UIColor.clearColor;
174
 			reactView.backgroundColor = UIColor.clearColor;
181
 
187
 
182
 - (void)setCustomNavigationComponentBackground {
188
 - (void)setCustomNavigationComponentBackground {
183
 	if (!_customTopBarBackground) {
189
 	if (!_customTopBarBackground) {
184
-		if (self.presenter.options.topBar.background.component.name) {
185
-			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.presenter.options.topBar.background.component];
190
+		if (self.options.topBar.background.component.name) {
191
+			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.options.topBar.background.component];
186
 			
192
 			
187
 			_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
193
 			_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
188
 			[self.navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
194
 			[self.navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
189
 		} else if (self.navigationController.navigationBar.subviews.count && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
195
 		} else if (self.navigationController.navigationBar.subviews.count && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
190
 			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
196
 			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
191
 		}
197
 		}
192
-		
193
-		if (self.presenter.options.topBar.background.clipToBounds) {
194
-			self.navigationController.navigationBar.clipsToBounds = YES;
195
-		} else {
196
-			self.navigationController.navigationBar.clipsToBounds = NO;
197
-		}
198
 	} if (_customTopBarBackground && _customTopBarBackground.superview == nil) {
198
 	} if (_customTopBarBackground && _customTopBarBackground.superview == nil) {
199
 		if (self.navigationController.navigationBar.subviews.count && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
199
 		if (self.navigationController.navigationBar.subviews.count && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
200
 			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
200
 			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
205
 }
205
 }
206
 
206
 
207
 -(BOOL)isCustomTransitioned {
207
 -(BOOL)isCustomTransitioned {
208
-	return self.presenter.options.customTransition.animations != nil;
208
+	return self.options.customTransition.animations != nil;
209
 }
209
 }
210
 
210
 
211
-- (BOOL)isCustomViewController {
212
-	return self.isExternalComponent;
211
+- (BOOL)isExternalViewController {
212
+	return !self.creator;
213
 }
213
 }
214
 
214
 
215
 - (BOOL)prefersStatusBarHidden {
215
 - (BOOL)prefersStatusBarHidden {
216
-	if (self.presenter.options.statusBar.visible) {
217
-		return ![self.presenter.options.statusBar.visible boolValue];
218
-	} else if ([self.presenter.options.statusBar.hideWithTopBar boolValue]) {
216
+	if (self.options.statusBar.visible) {
217
+		return ![self.options.statusBar.visible boolValue];
218
+	} else if ([self.options.statusBar.hideWithTopBar boolValue]) {
219
 		return self.navigationController.isNavigationBarHidden;
219
 		return self.navigationController.isNavigationBarHidden;
220
 	}
220
 	}
221
 	
221
 	
223
 }
223
 }
224
 
224
 
225
 - (UIStatusBarStyle)preferredStatusBarStyle {
225
 - (UIStatusBarStyle)preferredStatusBarStyle {
226
-	if (self.presenter.options.statusBar.style && [self.presenter.options.statusBar.style isEqualToString:@"light"]) {
226
+	if (self.options.statusBar.style && [self.options.statusBar.style isEqualToString:@"light"]) {
227
 		return UIStatusBarStyleLightContent;
227
 		return UIStatusBarStyleLightContent;
228
 	} else {
228
 	} else {
229
 		return UIStatusBarStyleDefault;
229
 		return UIStatusBarStyleDefault;
231
 }
231
 }
232
 
232
 
233
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
233
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
234
-	return self.presenter.options.layout.supportedOrientations;
234
+	return self.options.layout.supportedOrientations;
235
 }
235
 }
236
 
236
 
237
 - (BOOL)hidesBottomBarWhenPushed
237
 - (BOOL)hidesBottomBarWhenPushed
238
 {
238
 {
239
-	if (self.presenter.options.bottomTabs && self.presenter.options.bottomTabs.visible) {
240
-		return ![self.presenter.options.bottomTabs.visible boolValue];
239
+	if (self.options.bottomTabs && self.options.bottomTabs.visible) {
240
+		return ![self.options.bottomTabs.visible boolValue];
241
 	}
241
 	}
242
 	return NO;
242
 	return NO;
243
 }
243
 }
244
 
244
 
245
 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
245
 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
246
 	RNNRootViewController* vc =  (RNNRootViewController*)viewController;
246
 	RNNRootViewController* vc =  (RNNRootViewController*)viewController;
247
-	if (![vc.presenter.options.topBar.backButton.transition isEqualToString:@"custom"]){
247
+	if (![vc.options.topBar.backButton.transition isEqualToString:@"custom"]){
248
 		navigationController.delegate = nil;
248
 		navigationController.delegate = nil;
249
 	}
249
 	}
250
 }
250
 }
253
 								  animationControllerForOperation:(UINavigationControllerOperation)operation
253
 								  animationControllerForOperation:(UINavigationControllerOperation)operation
254
 											   fromViewController:(UIViewController*)fromVC
254
 											   fromViewController:(UIViewController*)fromVC
255
 												 toViewController:(UIViewController*)toVC {
255
 												 toViewController:(UIViewController*)toVC {
256
-	{
257
-		if (self.animator) {
258
-			return self.animator;
259
-		} else if (operation == UINavigationControllerOperationPush && self.presenter.options.animations.push.hasCustomAnimation) {
260
-			return [[RNNPushAnimation alloc] initWithScreenTransition:self.presenter.options.animations.push];
261
-		} else if (operation == UINavigationControllerOperationPop && self.presenter.options.animations.pop.hasCustomAnimation) {
262
-			return [[RNNPushAnimation alloc] initWithScreenTransition:self.presenter.options.animations.pop];
263
-		} else {
264
-			return nil;
265
-		}
256
+	if (self.animator) {
257
+		return self.animator;
258
+	} else if (operation == UINavigationControllerOperationPush && self.options.animations.push.hasCustomAnimation) {
259
+		return [[RNNPushAnimation alloc] initWithScreenTransition:self.options.animations.push];
260
+	} else if (operation == UINavigationControllerOperationPop && self.options.animations.pop.hasCustomAnimation) {
261
+		return [[RNNPushAnimation alloc] initWithScreenTransition:self.options.animations.pop];
262
+	} else {
263
+		return nil;
266
 	}
264
 	}
265
+	
267
 	return nil;
266
 	return nil;
268
 }
267
 }
269
 
268
 
270
 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
269
 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
271
-	return [[RNNModalAnimation alloc] initWithScreenTransition:self.presenter.options.animations.showModal isDismiss:NO];
270
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.showModal isDismiss:NO];
272
 }
271
 }
273
 
272
 
274
 - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
273
 - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
275
-	return [[RNNModalAnimation alloc] initWithScreenTransition:self.presenter.options.animations.dismissModal isDismiss:YES];
274
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.dismissModal isDismiss:YES];
276
 }
275
 }
277
 
276
 
278
 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
277
 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
307
 
306
 
308
 - (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
307
 - (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
309
 	NSMutableArray *actions = [[NSMutableArray alloc] init];
308
 	NSMutableArray *actions = [[NSMutableArray alloc] init];
310
-	for (NSDictionary *previewAction in self.presenter.options.preview.actions) {
309
+	for (NSDictionary *previewAction in self.options.preview.actions) {
311
 		UIPreviewAction *action = [self convertAction:previewAction];
310
 		UIPreviewAction *action = [self convertAction:previewAction];
312
 		NSDictionary *actionActions = previewAction[@"actions"];
311
 		NSDictionary *actionActions = previewAction[@"actions"];
313
 		if (actionActions.count > 0) {
312
 		if (actionActions.count > 0) {

+ 0
- 19
lib/ios/RNNSideMenu/MMDrawerController/MMDrawerController.m View File

21
 
21
 
22
 #import "MMDrawerController.h"
22
 #import "MMDrawerController.h"
23
 #import "UIViewController+MMDrawerController.h"
23
 #import "UIViewController+MMDrawerController.h"
24
-#import "RNNNavigationOptions.h"
25
 
24
 
26
 #import <QuartzCore/QuartzCore.h>
25
 #import <QuartzCore/QuartzCore.h>
27
 
26
 
480
     }
479
     }
481
 }
480
 }
482
 
481
 
483
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
484
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
485
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:childOptions];
486
-	}
487
-}
488
-
489
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
490
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
491
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:childOptions];
492
-	}
493
-}
494
-
495
-- (void)willMoveToParentViewController:(UIViewController *)parent {
496
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
497
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:nil];
498
-	}
499
-}
500
-
501
 -(void)setCenterViewController:(UIViewController *)newCenterViewController withCloseAnimation:(BOOL)animated completion:(void(^)(BOOL finished))completion{
482
 -(void)setCenterViewController:(UIViewController *)newCenterViewController withCloseAnimation:(BOOL)animated completion:(void(^)(BOOL finished))completion{
502
     
483
     
503
     if(self.openSide == MMDrawerSideNone){
484
     if(self.openSide == MMDrawerSideNone){

+ 3
- 9
lib/ios/RNNSideMenuChildVC.h View File

1
-//
2
-//  RNNSideMenuChildVC.h
3
-//  ReactNativeNavigation
4
-//
5
-//  Created by Ran Greenberg on 09/02/2017.
6
-//  Copyright © 2017 Wix. All rights reserved.
7
-//
8
-
9
 #import <UIKit/UIKit.h>
1
 #import <UIKit/UIKit.h>
10
 #import "RNNParentProtocol.h"
2
 #import "RNNParentProtocol.h"
11
 
3
 
23
 
15
 
24
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
16
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
25
 @property (nonatomic, retain) RNNBasePresenter* presenter;
17
 @property (nonatomic, retain) RNNBasePresenter* presenter;
18
+@property (nonatomic, strong) RNNNavigationOptions* options;
19
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
26
 
20
 
27
--(instancetype) initWithChild:(UIViewController<RNNParentProtocol>*)child type:(RNNSideMenuChildType)type;
21
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter type:(RNNSideMenuChildType)type;
28
 
22
 
29
 @end
23
 @end

+ 28
- 30
lib/ios/RNNSideMenuChildVC.m View File

1
-//
2
-//  RNNSideMenuChildVC.m
3
-//  ReactNativeNavigation
4
-//
5
-//  Created by Ran Greenberg on 09/02/2017.
6
-//  Copyright © 2017 Wix. All rights reserved.
7
-//
8
-
9
 #import "RNNSideMenuChildVC.h"
1
 #import "RNNSideMenuChildVC.h"
10
 
2
 
11
 @interface RNNSideMenuChildVC ()
3
 @interface RNNSideMenuChildVC ()
12
 
4
 
13
 @property (readwrite) RNNSideMenuChildType type;
5
 @property (readwrite) RNNSideMenuChildType type;
14
-@property (readwrite) UIViewController<RNNParentProtocol> *child;
6
+@property (nonatomic, retain) UIViewController<RNNParentProtocol> *child;
15
 
7
 
16
 @end
8
 @end
17
 
9
 
18
 @implementation RNNSideMenuChildVC
10
 @implementation RNNSideMenuChildVC
19
 
11
 
20
--(instancetype) initWithChild:(UIViewController<RNNParentProtocol>*)child type:(RNNSideMenuChildType)type {
12
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter type:(RNNSideMenuChildType)type {
13
+	self = [self initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
14
+	
15
+	self.type = type;
16
+
17
+	return self;
18
+}
19
+
20
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter {
21
 	self = [super init];
21
 	self = [super init];
22
 	
22
 	
23
+	self.presenter = presenter;
24
+	self.options = options;
25
+	self.layoutInfo = layoutInfo;
26
+	self.optionsResolver = optionsResolver;
27
+	
28
+	[self bindChildViewControllers:childViewControllers];
29
+	
30
+	return self;
31
+}
32
+
33
+- (void)bindChildViewControllers:(NSArray<UIViewController<RNNParentProtocol> *> *)viewControllers {
34
+	UIViewController<RNNParentProtocol>* child = viewControllers[0];
35
+	
23
 	self.child = child;
36
 	self.child = child;
24
 	[self addChildViewController:self.child];
37
 	[self addChildViewController:self.child];
25
 	[self.child.view setFrame:self.view.bounds];
38
 	[self.child.view setFrame:self.view.bounds];
26
 	[self.view addSubview:self.child.view];
39
 	[self.view addSubview:self.child.view];
27
 	[self.view bringSubviewToFront:self.child.view];
40
 	[self.view bringSubviewToFront:self.child.view];
28
-
29
-	self.type = type;
30
-	
31
-	return self;
32
 }
41
 }
33
 
42
 
34
 - (UIViewController *)getLeafViewController {
43
 - (UIViewController *)getLeafViewController {
35
 	return [self.child getLeafViewController];
44
 	return [self.child getLeafViewController];
36
 }
45
 }
37
 
46
 
38
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
39
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
40
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
41
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
42
-	}
43
-}
44
-
45
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
46
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
47
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
48
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
49
-	}
47
+- (void)willMoveToParentViewController:(UIViewController *)parent {
48
+	[_optionsResolver resolve:self with:self.childViewControllers];
49
+	[_presenter present:self.options onViewControllerDidLoad:self];
50
 }
50
 }
51
 
51
 
52
-- (void)willMoveToParentViewController:(UIViewController *)parent {
53
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
54
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:_presenter.options];
55
-	}
52
+- (void)mergeOptions:(RNNNavigationOptions *)options {
53
+	[self.presenter present:options onViewControllerWillAppear:self];
56
 }
54
 }
57
 
55
 
58
 - (UIStatusBarStyle)preferredStatusBarStyle {
56
 - (UIStatusBarStyle)preferredStatusBarStyle {

+ 2
- 2
lib/ios/RNNSideMenuController.h View File

20
 
20
 
21
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
21
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
22
 @property (nonatomic, retain) RNNBasePresenter* presenter;
22
 @property (nonatomic, retain) RNNBasePresenter* presenter;
23
-
24
--(instancetype)initWithControllers:(NSArray*)controllers presenter:(RNNBasePresenter *)presenter;
23
+@property (nonatomic, strong) RNNNavigationOptions* options;
24
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
25
 
25
 
26
 -(void)showSideMenu:(MMDrawerSide)side animated:(BOOL)animated;
26
 -(void)showSideMenu:(MMDrawerSide)side animated:(BOOL)animated;
27
 -(void)hideSideMenu:(MMDrawerSide)side animated:(BOOL)animated;
27
 -(void)hideSideMenu:(MMDrawerSide)side animated:(BOOL)animated;

+ 18
- 23
lib/ios/RNNSideMenuController.m View File

21
 
21
 
22
 @implementation RNNSideMenuController
22
 @implementation RNNSideMenuController
23
 
23
 
24
--(instancetype)initWithControllers:(NSArray*)controllers presenter:(RNNBasePresenter *)presenter
25
-{
24
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter {
26
 	self = [super init];
25
 	self = [super init];
26
+	
27
 	self.presenter = presenter;
27
 	self.presenter = presenter;
28
+	self.options = options;
29
+	self.layoutInfo = layoutInfo;
30
+	self.optionsResolver = optionsResolver;
31
+	
32
+	[self bindChildViewControllers:childViewControllers];
28
 	
33
 	
29
-	[self setControllers:controllers];
34
+	return self;
35
+}
36
+
37
+- (void)bindChildViewControllers:(NSArray<UIViewController<RNNLayoutProtocol> *> *)viewControllers {
38
+	[self setControllers:viewControllers];
30
 	
39
 	
31
 	self.sideMenu = [[MMDrawerController alloc] initWithCenterViewController:self.center leftDrawerViewController:self.left rightDrawerViewController:self.right];
40
 	self.sideMenu = [[MMDrawerController alloc] initWithCenterViewController:self.center leftDrawerViewController:self.left rightDrawerViewController:self.right];
32
 	
41
 	
33
 	self.sideMenu.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
42
 	self.sideMenu.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
34
 	self.sideMenu.closeDrawerGestureModeMask = MMCloseDrawerGestureModeAll;
43
 	self.sideMenu.closeDrawerGestureModeMask = MMCloseDrawerGestureModeAll;
35
-
44
+	
36
 	[self addChildViewController:self.sideMenu];
45
 	[self addChildViewController:self.sideMenu];
37
 	[self.sideMenu.view setFrame:self.view.bounds];
46
 	[self.sideMenu.view setFrame:self.view.bounds];
38
 	[self.view addSubview:self.sideMenu.view];
47
 	[self.view addSubview:self.sideMenu.view];
39
 	[self.view bringSubviewToFront:self.sideMenu.view];
48
 	[self.view bringSubviewToFront:self.sideMenu.view];
40
-	
41
-	return self;
42
 }
49
 }
43
 
50
 
44
 -(void)showSideMenu:(MMDrawerSide)side animated:(BOOL)animated {
51
 -(void)showSideMenu:(MMDrawerSide)side animated:(BOOL)animated {
94
 	return [self.center getLeafViewController];
101
 	return [self.center getLeafViewController];
95
 }
102
 }
96
 
103
 
97
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
98
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
99
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
100
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
101
-	}
102
-}
103
-
104
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
105
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
106
-		if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
107
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
108
-	}
109
-}
110
-
111
 - (void)willMoveToParentViewController:(UIViewController *)parent {
104
 - (void)willMoveToParentViewController:(UIViewController *)parent {
112
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
113
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:_presenter.options];
114
-	}
105
+	[_optionsResolver resolve:self with:self.childViewControllers];
106
+	[_presenter present:self.options onViewControllerDidLoad:self];
115
 }
107
 }
116
 
108
 
109
+- (void)mergeOptions:(RNNNavigationOptions *)options {
110
+	[self.presenter present:options onViewControllerWillAppear:self];
111
+}
117
 
112
 
118
 @end
113
 @end

+ 15
- 2
lib/ios/RNNSideMenuSideOptions.m View File

5
 @implementation RNNSideMenuSideOptions
5
 @implementation RNNSideMenuSideOptions
6
 
6
 
7
 - (void)applyOnSide:(MMDrawerSide)side viewController:(UIViewController *)viewController {
7
 - (void)applyOnSide:(MMDrawerSide)side viewController:(UIViewController *)viewController {
8
-	RNNSideMenuController* sideMenuController = (RNNSideMenuController*)UIApplication.sharedApplication.delegate.window.rootViewController;
9
-	if (sideMenuController && [sideMenuController isKindOfClass:[RNNSideMenuController class]]) {
8
+	RNNSideMenuController* sideMenuController = [self getParentSideMenuControllerFromChild:viewController];
9
+	if (sideMenuController) {
10
 		if (self.enabled) {
10
 		if (self.enabled) {
11
 			switch (side) {
11
 			switch (side) {
12
 				case MMDrawerSideRight:
12
 				case MMDrawerSideRight:
62
 	[self resetOptions];
62
 	[self resetOptions];
63
 }
63
 }
64
 
64
 
65
+- (RNNSideMenuController *)getParentSideMenuControllerFromChild:(UIViewController *)childViewController {
66
+	UIViewController* vc = childViewController;
67
+	while (vc) {
68
+		if ([vc isKindOfClass:[RNNSideMenuController class]]) {
69
+			return (RNNSideMenuController *)vc;
70
+		}
71
+		
72
+		vc = vc.parentViewController;
73
+	}
74
+	
75
+	return nil;
76
+}
77
+
65
 - (void)resetOptions {
78
 - (void)resetOptions {
66
 	self.visible = nil;
79
 	self.visible = nil;
67
 	self.enabled = nil;
80
 	self.enabled = nil;

+ 3
- 10
lib/ios/RNNSplitViewController.h View File

10
 #import "RNNTopTabsViewController.h"
10
 #import "RNNTopTabsViewController.h"
11
 #import "RNNParentProtocol.h"
11
 #import "RNNParentProtocol.h"
12
 
12
 
13
-@interface RNNSplitViewController : UISplitViewController	<RNNParentProtocol>
13
+@interface RNNSplitViewController : UISplitViewController <RNNParentProtocol>
14
 
14
 
15
-@property (nonatomic, strong) RNNSplitViewOptions* options;
16
-@property (nonatomic, strong) RNNEventEmitter *eventEmitter;
17
-@property (nonatomic, strong) NSString* componentId;
15
+@property (nonatomic, strong) RNNNavigationOptions* options;
18
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
16
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
19
 @property (nonatomic, retain) RNNBasePresenter* presenter;
17
 @property (nonatomic, retain) RNNBasePresenter* presenter;
20
-@property (nonatomic) id<RNNRootViewCreator> creator;
21
-
22
--(instancetype)initWithOptions:(RNNSplitViewOptions*)options
23
-			withComponentId:(NSString*)componentId
24
-			rootViewCreator:(id<RNNRootViewCreator>)creator
25
-				  eventEmitter:(RNNEventEmitter*)eventEmitter;
18
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
26
 
19
 
27
 @end
20
 @end

+ 20
- 19
lib/ios/RNNSplitViewController.m View File

2
 
2
 
3
 @implementation RNNSplitViewController
3
 @implementation RNNSplitViewController
4
 
4
 
5
--(instancetype)initWithOptions:(RNNSplitViewOptions*)options
6
-			withComponentId:(NSString*)componentId
7
-			rootViewCreator:(id<RNNRootViewCreator>)creator
8
-			   eventEmitter:(RNNEventEmitter*)eventEmitter {
5
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter {
9
 	self = [super init];
6
 	self = [super init];
10
-	self.componentId = componentId;
7
+	
8
+	self.presenter = presenter;
11
 	self.options = options;
9
 	self.options = options;
12
-	self.eventEmitter = eventEmitter;
13
-	self.creator = creator;
14
-
10
+	self.layoutInfo = layoutInfo;
11
+	self.optionsResolver = optionsResolver;
12
+	
15
 	self.navigationController.delegate = self;
13
 	self.navigationController.delegate = self;
16
-
14
+	
15
+	[self bindChildViewControllers:childViewControllers];
16
+	
17
 	return self;
17
 	return self;
18
 }
18
 }
19
 
19
 
20
+- (void)bindChildViewControllers:(NSArray<UIViewController<RNNLayoutProtocol> *> *)viewControllers {
21
+	[self setViewControllers:viewControllers];
22
+	UIViewController<UISplitViewControllerDelegate>* masterViewController = viewControllers[0];
23
+	self.delegate = masterViewController;
24
+}
25
+
20
 -(void)viewWillAppear:(BOOL)animated{
26
 -(void)viewWillAppear:(BOOL)animated{
21
 	[super viewWillAppear:animated];
27
 	[super viewWillAppear:animated];
22
 	[self.options applyOn:self];
28
 	[self.options applyOn:self];
26
 	return self;
32
 	return self;
27
 }
33
 }
28
 
34
 
29
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
30
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
31
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
32
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
33
-	}
35
+- (void)willMoveToParentViewController:(UIViewController *)parent {
36
+	[_optionsResolver resolve:self with:self.viewControllers];
37
+	[_presenter present:self.options onViewControllerDidLoad:self];
34
 }
38
 }
35
 
39
 
36
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
37
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
38
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
39
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
40
-	}
40
+- (void)mergeOptions:(RNNNavigationOptions *)options {
41
+	[self.presenter present:options onViewControllerWillAppear:self];
41
 }
42
 }
42
 
43
 
43
 @end
44
 @end

+ 3
- 1
lib/ios/RNNTabBarController.h View File

5
 
5
 
6
 @interface RNNTabBarController : UITabBarController <RNNParentProtocol, UITabBarControllerDelegate>
6
 @interface RNNTabBarController : UITabBarController <RNNParentProtocol, UITabBarControllerDelegate>
7
 
7
 
8
-- (instancetype)initWithEventEmitter:(RNNEventEmitter*)eventEmitter;
8
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter eventEmitter:(RNNEventEmitter *)eventEmitter;
9
 
9
 
10
 - (void)setSelectedIndexByComponentID:(NSString *)componentID;
10
 - (void)setSelectedIndexByComponentID:(NSString *)componentID;
11
 
11
 
12
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
12
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
13
 @property (nonatomic, retain) RNNBasePresenter* presenter;
13
 @property (nonatomic, retain) RNNBasePresenter* presenter;
14
+@property (nonatomic, strong) RNNNavigationOptions* options;
15
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
14
 
16
 
15
 @end
17
 @end

+ 36
- 15
lib/ios/RNNTabBarController.m View File

8
 	RNNEventEmitter *_eventEmitter;
8
 	RNNEventEmitter *_eventEmitter;
9
 }
9
 }
10
 
10
 
11
-- (instancetype)initWithEventEmitter:(id)eventEmitter {
12
-	self = [super init];
11
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
12
+			  childViewControllers:(NSArray *)childViewControllers
13
+						   options:(RNNNavigationOptions *)options
14
+				   optionsResolver:(RNNParentOptionsResolver *)optionsResolver
15
+						 presenter:(RNNBasePresenter *)presenter
16
+					  eventEmitter:(RNNEventEmitter *)eventEmitter {
17
+	self = [self initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options optionsResolver:optionsResolver presenter:presenter];
18
+	
13
 	_eventEmitter = eventEmitter;
19
 	_eventEmitter = eventEmitter;
14
-	self.delegate = self;
20
+	
15
 	return self;
21
 	return self;
16
 }
22
 }
17
 
23
 
18
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
19
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
20
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
21
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
22
-	}
24
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
25
+			  childViewControllers:(NSArray *)childViewControllers
26
+						   options:(RNNNavigationOptions *)options
27
+				   optionsResolver:(RNNParentOptionsResolver *)optionsResolver
28
+						 presenter:(RNNBasePresenter *)presenter {
29
+	self = [super init];
30
+	
31
+	self.presenter = presenter;
32
+	self.options = options;
33
+	self.layoutInfo = layoutInfo;
34
+	self.optionsResolver = optionsResolver;
35
+	
36
+	[self setViewControllers:childViewControllers];
37
+	
38
+	return self;
23
 }
39
 }
24
 
40
 
25
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
26
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
27
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
28
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
29
-	}
41
+- (instancetype)initWithEventEmitter:(id)eventEmitter {
42
+	self = [super init];
43
+	_eventEmitter = eventEmitter;
44
+	self.delegate = self;
45
+	return self;
30
 }
46
 }
31
 
47
 
32
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
48
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
56
 	return ((UIViewController<RNNParentProtocol>*)self.selectedViewController).preferredStatusBarStyle;
72
 	return ((UIViewController<RNNParentProtocol>*)self.selectedViewController).preferredStatusBarStyle;
57
 }
73
 }
58
 
74
 
59
-- (void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers {
60
-	[super setViewControllers:viewControllers];
75
+- (void)willMoveToParentViewController:(UIViewController *)parent {
76
+	[_optionsResolver resolve:self with:self.viewControllers];
77
+	[_presenter present:self.options onViewControllerDidLoad:self];
78
+}
79
+
80
+- (void)mergeOptions:(RNNNavigationOptions *)options {
81
+	[self.presenter present:options onViewControllerWillAppear:self];
61
 }
82
 }
62
 
83
 
63
 #pragma mark UITabBarControllerDelegate
84
 #pragma mark UITabBarControllerDelegate

+ 2
- 6
lib/ios/RNNTabBarPresenter.m View File

2
 
2
 
3
 @implementation RNNTabBarPresenter
3
 @implementation RNNTabBarPresenter
4
 
4
 
5
-- (void)presentOn:(UITabBarController *)tabBarController {
6
-	[self.options applyOnTabBarController:tabBarController];
7
-}
8
-
9
-- (void)present:(RNNNavigationOptions *)options on:(UITabBarController *)tabBarController {
10
-	[self.options applyOnTabBarController:tabBarController];
5
+- (void)present:(RNNNavigationOptions *)options onViewControllerDidLoad:(UITabBarController *)tabBarController {
6
+	[options applyOnTabBarController:tabBarController];
11
 }
7
 }
12
 
8
 
13
 @end
9
 @end

+ 3
- 0
lib/ios/RNNTopTabsViewController.h View File

6
 @interface RNNTopTabsViewController : UIViewController <RNNParentProtocol>
6
 @interface RNNTopTabsViewController : UIViewController <RNNParentProtocol>
7
 
7
 
8
 @property (nonatomic, retain) UIView* contentView;
8
 @property (nonatomic, retain) UIView* contentView;
9
+
9
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
10
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
10
 @property (nonatomic, retain) RNNBasePresenter* presenter;
11
 @property (nonatomic, retain) RNNBasePresenter* presenter;
12
+@property (nonatomic, strong) RNNNavigationOptions* options;
13
+@property (nonatomic, strong) RNNParentOptionsResolver* optionsResolver;
11
 
14
 
12
 - (void)setViewControllers:(NSArray*)viewControllers;
15
 - (void)setViewControllers:(NSArray*)viewControllers;
13
 - (void)viewController:(UIViewController*)vc changedTitle:(NSString*)title;
16
 - (void)viewController:(UIViewController*)vc changedTitle:(NSString*)title;

+ 23
- 15
lib/ios/RNNTopTabsViewController.m View File

13
 
13
 
14
 @implementation RNNTopTabsViewController
14
 @implementation RNNTopTabsViewController
15
 
15
 
16
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options optionsResolver:(RNNParentOptionsResolver *)optionsResolver presenter:(RNNBasePresenter *)presenter {
17
+	self = [self init];
18
+	
19
+	self.presenter = presenter;
20
+	self.options = options;
21
+	self.layoutInfo = layoutInfo;
22
+	self.optionsResolver = optionsResolver;
23
+	
24
+	[self setViewControllers:childViewControllers];
25
+	
26
+	return self;
27
+}
28
+
16
 - (instancetype)init {
29
 - (instancetype)init {
17
 	self = [super init];
30
 	self = [super init];
18
 	
31
 	
57
 	_viewControllers = viewControllers;
70
 	_viewControllers = viewControllers;
58
 	for (RNNRootViewController* childVc in viewControllers) {
71
 	for (RNNRootViewController* childVc in viewControllers) {
59
 		[childVc.view setFrame:_contentView.bounds];
72
 		[childVc.view setFrame:_contentView.bounds];
60
-		[childVc.presenter.options.topTab applyOn:childVc];
73
+		[childVc.options.topTab applyOn:childVc];
61
 	}
74
 	}
62
 	
75
 	
63
 	[self setSelectedViewControllerIndex:0];
76
 	[self setSelectedViewControllerIndex:0];
72
     [super viewDidLoad];
85
     [super viewDidLoad];
73
 }
86
 }
74
 
87
 
75
-#pragma mark RNNParentProtocol
76
-
77
-- (UIViewController *)getLeafViewController {
78
-	return _currentViewController;
88
+- (void)willMoveToParentViewController:(UIViewController *)parent {
89
+	[_optionsResolver resolve:self with:_viewControllers];
90
+	[_presenter present:self.options onViewControllerDidLoad:self];
79
 }
91
 }
80
 
92
 
81
-- (void)performOnChildLoad:(RNNNavigationOptions *)childOptions {
82
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
83
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildLoad:)]) {
84
-		[self.parentViewController performSelector:@selector(performOnChildLoad:) withObject:combinedOptions];
85
-	}
93
+- (void)mergeOptions:(RNNNavigationOptions *)options {
94
+	[self.presenter present:options onViewControllerWillAppear:self];
86
 }
95
 }
87
 
96
 
88
-- (void)performOnChildWillAppear:(RNNNavigationOptions *)childOptions {
89
-	RNNNavigationOptions* combinedOptions = [_presenter presentWithChildOptions:childOptions on:self];
90
-	if ([self.parentViewController respondsToSelector:@selector(performOnChildWillAppear:)]) {
91
-		[self.parentViewController performSelector:@selector(performOnChildWillAppear:) withObject:combinedOptions];
92
-	}
97
+#pragma mark RNNParentProtocol
98
+
99
+- (UIViewController *)getLeafViewController {
100
+	return _currentViewController;
93
 }
101
 }
94
 
102
 
95
 @end
103
 @end

+ 0
- 2
lib/ios/RNNViewControllerPresenter.h View File

3
 
3
 
4
 @interface RNNViewControllerPresenter : RNNBasePresenter
4
 @interface RNNViewControllerPresenter : RNNBasePresenter
5
 
5
 
6
-- (void)presentOn:(UIViewController *)viewController;
7
-
8
 @end
6
 @end

+ 2
- 6
lib/ios/RNNViewControllerPresenter.m View File

2
 
2
 
3
 @implementation RNNViewControllerPresenter
3
 @implementation RNNViewControllerPresenter
4
 
4
 
5
-- (void)presentOn:(UIViewController *)viewController {
6
-	[self.options applyOn:viewController];
7
-	
8
-	if ([self.delegate respondsToSelector:@selector(optionsUpdated)]) {
9
-		[self.delegate optionsUpdated];
10
-	}
5
+- (void)present:(RNNNavigationOptions *)options onViewControllerDidLoad:(UIViewController *)viewController {
6
+	[options applyOn:viewController];
11
 }
7
 }
12
 
8
 
13
 @end
9
 @end

+ 8
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

115
 		50644A2120E11A720026709C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 50644A1F20E11A720026709C /* Constants.m */; };
115
 		50644A2120E11A720026709C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 50644A1F20E11A720026709C /* Constants.m */; };
116
 		506A2B1420973DFD00F43A95 /* RNNErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */; };
116
 		506A2B1420973DFD00F43A95 /* RNNErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */; };
117
 		506A2B1520973DFD00F43A95 /* RNNErrorHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */; };
117
 		506A2B1520973DFD00F43A95 /* RNNErrorHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */; };
118
+		506F62E22163912E00AD0D0A /* RNNParentOptionsResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 506F62E02163912E00AD0D0A /* RNNParentOptionsResolver.h */; };
119
+		506F62E32163912E00AD0D0A /* RNNParentOptionsResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F62E12163912E00AD0D0A /* RNNParentOptionsResolver.m */; };
118
 		50706E6D20CE7CA5003345C3 /* UIImage+tint.h in Headers */ = {isa = PBXBuildFile; fileRef = 50706E6B20CE7CA5003345C3 /* UIImage+tint.h */; };
120
 		50706E6D20CE7CA5003345C3 /* UIImage+tint.h in Headers */ = {isa = PBXBuildFile; fileRef = 50706E6B20CE7CA5003345C3 /* UIImage+tint.h */; };
119
 		50706E6E20CE7CA5003345C3 /* UIImage+tint.m in Sources */ = {isa = PBXBuildFile; fileRef = 50706E6C20CE7CA5003345C3 /* UIImage+tint.m */; };
121
 		50706E6E20CE7CA5003345C3 /* UIImage+tint.m in Sources */ = {isa = PBXBuildFile; fileRef = 50706E6C20CE7CA5003345C3 /* UIImage+tint.m */; };
120
 		50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50762D06205E96C200E3D18A /* RNNModalAnimation.h */; };
122
 		50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50762D06205E96C200E3D18A /* RNNModalAnimation.h */; };
358
 		50644A1F20E11A720026709C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
360
 		50644A1F20E11A720026709C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
359
 		506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNErrorHandler.h; sourceTree = "<group>"; };
361
 		506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNErrorHandler.h; sourceTree = "<group>"; };
360
 		506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNErrorHandler.m; sourceTree = "<group>"; };
362
 		506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNErrorHandler.m; sourceTree = "<group>"; };
363
+		506F62E02163912E00AD0D0A /* RNNParentOptionsResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNParentOptionsResolver.h; sourceTree = "<group>"; };
364
+		506F62E12163912E00AD0D0A /* RNNParentOptionsResolver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNParentOptionsResolver.m; sourceTree = "<group>"; };
361
 		50706E6B20CE7CA5003345C3 /* UIImage+tint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+tint.h"; sourceTree = "<group>"; };
365
 		50706E6B20CE7CA5003345C3 /* UIImage+tint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+tint.h"; sourceTree = "<group>"; };
362
 		50706E6C20CE7CA5003345C3 /* UIImage+tint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+tint.m"; sourceTree = "<group>"; };
366
 		50706E6C20CE7CA5003345C3 /* UIImage+tint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+tint.m"; sourceTree = "<group>"; };
363
 		50762D06205E96C200E3D18A /* RNNModalAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNModalAnimation.h; sourceTree = "<group>"; };
367
 		50762D06205E96C200E3D18A /* RNNModalAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNModalAnimation.h; sourceTree = "<group>"; };
702
 				50570BE82063E09B006A1B5C /* RNNTitleViewHelper.h */,
706
 				50570BE82063E09B006A1B5C /* RNNTitleViewHelper.h */,
703
 				501CD31D214A5B6900A6E225 /* RNNLayoutInfo.h */,
707
 				501CD31D214A5B6900A6E225 /* RNNLayoutInfo.h */,
704
 				501CD31E214A5B6900A6E225 /* RNNLayoutInfo.m */,
708
 				501CD31E214A5B6900A6E225 /* RNNLayoutInfo.m */,
709
+				506F62E02163912E00AD0D0A /* RNNParentOptionsResolver.h */,
710
+				506F62E12163912E00AD0D0A /* RNNParentOptionsResolver.m */,
705
 				50220F46212ABDFD004C2B0A /* RNNReactRootView.h */,
711
 				50220F46212ABDFD004C2B0A /* RNNReactRootView.h */,
706
 				50220F47212ABDFD004C2B0A /* RNNReactRootView.m */,
712
 				50220F47212ABDFD004C2B0A /* RNNReactRootView.m */,
707
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
713
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
912
 				50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */,
918
 				50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */,
913
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
919
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
914
 				E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */,
920
 				E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */,
921
+				506F62E22163912E00AD0D0A /* RNNParentOptionsResolver.h in Headers */,
915
 				505EDD34214E7B7B0071C7DE /* RNNLeafProtocol.h in Headers */,
922
 				505EDD34214E7B7B0071C7DE /* RNNLeafProtocol.h in Headers */,
916
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
923
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
917
 				50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */,
924
 				50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */,
1181
 				50F5DFC61F407AA0001A00BC /* RNNNavigationController.m in Sources */,
1188
 				50F5DFC61F407AA0001A00BC /* RNNNavigationController.m in Sources */,
1182
 				21B85E5D1F44480200B314B5 /* RNNNavigationButtons.m in Sources */,
1189
 				21B85E5D1F44480200B314B5 /* RNNNavigationButtons.m in Sources */,
1183
 				E8E518371F83B94A000467AC /* RNNViewLocation.m in Sources */,
1190
 				E8E518371F83B94A000467AC /* RNNViewLocation.m in Sources */,
1191
+				506F62E32163912E00AD0D0A /* RNNParentOptionsResolver.m in Sources */,
1184
 				E3458D3E20BD9CE40023149B /* RNNPreviewOptions.m in Sources */,
1192
 				E3458D3E20BD9CE40023149B /* RNNPreviewOptions.m in Sources */,
1185
 				263905C91E4C6F440023D7D3 /* SidebarFlipboardAnimation.m in Sources */,
1193
 				263905C91E4C6F440023D7D3 /* SidebarFlipboardAnimation.m in Sources */,
1186
 			);
1194
 			);

+ 7
- 5
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

97
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
97
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
98
 	initialOptions.topBar.title.text = @"the title";
98
 	initialOptions.topBar.title.text = @"the title";
99
 	RNNLayoutInfo* layoutInfo = [RNNLayoutInfo new];
99
 	RNNLayoutInfo* layoutInfo = [RNNLayoutInfo new];
100
+	RNNTestRootViewCreator* creator = [[RNNTestRootViewCreator alloc] init];
100
 	
101
 	
101
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithOptions:initialOptions];
102
-	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:[[RNNTestRootViewCreator alloc] init] eventEmitter:nil isExternalComponent:NO presenter:presenter];
102
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
103
+	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:creator eventEmitter:nil presenter:presenter options:initialOptions];
103
 	
104
 	
104
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
105
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
105
-	nav.presenter = [[RNNNavigationControllerPresenter alloc] initWithOptions:initialOptions];
106
+	nav.presenter = [[RNNNavigationControllerPresenter alloc] init];
107
+	nav.options = initialOptions;
106
 	
108
 	
107
 	[vc viewWillAppear:false];
109
 	[vc viewWillAppear:false];
108
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
110
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
123
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
125
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
124
 	initialOptions.topBar.title.text = @"the title";
126
 	initialOptions.topBar.title.text = @"the title";
125
 	
127
 	
126
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithOptions:initialOptions];
127
-	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:[[RNNTestRootViewCreator alloc] init] eventEmitter:nil isExternalComponent:NO presenter:presenter];
128
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
129
+	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:[[RNNTestRootViewCreator alloc] init] eventEmitter:nil presenter:presenter options:initialOptions];
128
 	
130
 	
129
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
131
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
130
 	[vc viewWillAppear:false];
132
 	[vc viewWillAppear:false];

+ 46
- 7
lib/ios/ReactNativeNavigationTests/RNNNavigationControllerTest.m View File

12
 	RNNRootViewController* _vc1;
12
 	RNNRootViewController* _vc1;
13
 	RNNRootViewController* _vc2;
13
 	RNNRootViewController* _vc2;
14
 	UIViewController* _vc3;
14
 	UIViewController* _vc3;
15
-	RNNViewControllerPresenter* _presenter;
16
 }
15
 }
17
 
16
 
18
 - (void)setUp {
17
 - (void)setUp {
19
     [super setUp];
18
     [super setUp];
20
 	
19
 	
21
-	_presenter = [[RNNViewControllerPresenter alloc] initWithOptions:[[RNNNavigationOptions alloc] initWithDict:@{}]];
22
-	self.uut = [[RNNNavigationController alloc] init];
23
-	_vc1 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil isExternalComponent:NO presenter:_presenter];
24
-	_vc2 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil isExternalComponent:NO presenter:_presenter];
20
+	_vc1 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[[RNNViewControllerPresenter alloc] init] options:nil];
21
+	_vc2 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[[RNNViewControllerPresenter alloc] init] options:nil];
25
 	_vc3 = [UIViewController new];
22
 	_vc3 = [UIViewController new];
23
+	
24
+	self.uut = [[RNNNavigationController alloc] initWithRootViewController:_vc1];
25
+	self.uut.options = [[RNNNavigationOptions alloc] initWithDict:@{}];
26
+	self.uut.presenter = [[RNNNavigationControllerPresenter alloc] init];;
26
 }
27
 }
27
 
28
 
28
 - (void)testChildViewControllerForStatusBarStyle_shouldReturnTopViewController {
29
 - (void)testChildViewControllerForStatusBarStyle_shouldReturnTopViewController {
34
 }
35
 }
35
 
36
 
36
 - (void)testPreferredStatusBarStyle_shouldReturnLeafPreferredStatusBarStyle {
37
 - (void)testPreferredStatusBarStyle_shouldReturnLeafPreferredStatusBarStyle {
37
-	[self.uut setViewControllers:@[_vc1]];
38
-	self.uut.getLeafViewController.presenter.options.statusBar.style = @"light";
38
+	self.uut.getLeafViewController.options.statusBar.style = @"light";
39
 	XCTAssertTrue(self.uut.preferredStatusBarStyle == self.uut.getLeafViewController.preferredStatusBarStyle);
39
 	XCTAssertTrue(self.uut.preferredStatusBarStyle == self.uut.getLeafViewController.preferredStatusBarStyle);
40
 }
40
 }
41
 
41
 
42
+- (void)testPopGestureEnabled_false {
43
+	NSNumber* popGestureEnabled = @(0);
44
+	self.uut.options.popGesture = popGestureEnabled;
45
+	
46
+	[self.uut viewDidLoad];
47
+
48
+	XCTAssertFalse(self.uut.interactivePopGestureRecognizer.enabled);
49
+}
50
+
51
+- (void)testPopGestureEnabled_true {
52
+	NSNumber* popGestureEnabled = @(1);
53
+	self.uut.options.popGesture = popGestureEnabled;
54
+	
55
+	[self.uut viewDidLoad];
56
+	
57
+	XCTAssertTrue(self.uut.interactivePopGestureRecognizer.enabled);
58
+}
59
+
60
+- (void)testRootBackgroundImage {
61
+	UIImage* rootBackgroundImage = [[UIImage alloc] init];
62
+	self.uut.options.rootBackgroundImage = rootBackgroundImage;
63
+	[self.uut viewDidLoad];
64
+	XCTAssertTrue([[(UIImageView*)self.uut.view.subviews[0] image] isEqual:rootBackgroundImage]);
65
+}
66
+
67
+- (void)testTopBarBackgroundClipToBounds_true {
68
+	self.uut.options.topBar.background.clipToBounds = @(1);
69
+	[self.uut viewDidLoad];
70
+
71
+	XCTAssertTrue(self.uut.navigationBar.clipsToBounds);
72
+}
73
+
74
+- (void)testTopBarBackgroundClipToBounds_false {
75
+	self.uut.options.topBar.background.clipToBounds = @(0);
76
+	[self.uut viewDidLoad];
77
+
78
+	XCTAssertFalse(self.uut.navigationController.navigationBar.clipsToBounds);
79
+}
80
+
42
 
81
 
43
 @end
82
 @end

+ 8
- 64
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

48
 	layoutInfo.componentId = self.componentId;
48
 	layoutInfo.componentId = self.componentId;
49
 	layoutInfo.name = self.pageName;
49
 	layoutInfo.name = self.pageName;
50
 	
50
 	
51
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithOptions:self.options];
52
-	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:self.creator eventEmitter:self.emitter isExternalComponent:NO presenter:presenter];
51
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
52
+	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:self.creator eventEmitter:self.emitter presenter:presenter options:self.options];
53
 }
53
 }
54
 
54
 
55
 -(void)testTopBarBackgroundColor_validColor{
55
 -(void)testTopBarBackgroundColor_validColor{
70
 }
70
 }
71
 
71
 
72
 - (void)testStatusBarHidden_default {
72
 - (void)testStatusBarHidden_default {
73
-	__unused RNNNavigationController* nav = [self createNavigationController];
74
 	[self.uut viewWillAppear:false];
73
 	[self.uut viewWillAppear:false];
75
 
74
 
76
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
75
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
78
 
77
 
79
 - (void)testStatusBarVisible_false {
78
 - (void)testStatusBarVisible_false {
80
 	self.options.statusBar.visible = @(0);
79
 	self.options.statusBar.visible = @(0);
81
-	__unused RNNNavigationController* nav = [self createNavigationController];
82
 	[self.uut viewWillAppear:false];
80
 	[self.uut viewWillAppear:false];
83
 
81
 
84
 	XCTAssertTrue([self.uut prefersStatusBarHidden]);
82
 	XCTAssertTrue([self.uut prefersStatusBarHidden]);
86
 
84
 
87
 - (void)testStatusBarVisible_true {
85
 - (void)testStatusBarVisible_true {
88
 	self.options.statusBar.visible = @(1);
86
 	self.options.statusBar.visible = @(1);
89
-	__unused RNNNavigationController* nav = [self createNavigationController];
90
 	[self.uut viewWillAppear:false];
87
 	[self.uut viewWillAppear:false];
91
 	
88
 	
92
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
89
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
95
 - (void)testStatusBarHideWithTopBar_false {
92
 - (void)testStatusBarHideWithTopBar_false {
96
 	self.options.statusBar.hideWithTopBar = @(0);
93
 	self.options.statusBar.hideWithTopBar = @(0);
97
 	self.options.topBar.visible = @(0);
94
 	self.options.topBar.visible = @(0);
98
-	__unused RNNNavigationController* nav = [self createNavigationController];
99
 	[self.uut viewWillAppear:false];
95
 	[self.uut viewWillAppear:false];
100
 
96
 
101
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
97
 	XCTAssertFalse([self.uut prefersStatusBarHidden]);
105
 	self.options.statusBar.hideWithTopBar = @(1);
101
 	self.options.statusBar.hideWithTopBar = @(1);
106
 	self.options.topBar.visible = @(0);
102
 	self.options.topBar.visible = @(0);
107
 	__unused RNNNavigationController* nav = [self createNavigationController];
103
 	__unused RNNNavigationController* nav = [self createNavigationController];
104
+
108
 	[self.uut viewWillAppear:false];
105
 	[self.uut viewWillAppear:false];
109
 
106
 
110
 	XCTAssertTrue([self.uut prefersStatusBarHidden]);
107
 	XCTAssertTrue([self.uut prefersStatusBarHidden]);
113
 -(void)testTitle_string{
110
 -(void)testTitle_string{
114
 	NSString* title =@"some title";
111
 	NSString* title =@"some title";
115
 	self.options.topBar.title.text = title;
112
 	self.options.topBar.title.text = title;
116
-	__unused RNNNavigationController* nav = [self createNavigationController];
117
 
113
 
118
 	[self.uut viewWillAppear:false];
114
 	[self.uut viewWillAppear:false];
119
 	XCTAssertTrue([self.uut.navigationItem.title isEqual:title]);
115
 	XCTAssertTrue([self.uut.navigationItem.title isEqual:title]);
120
 }
116
 }
121
 
117
 
122
 -(void)testTitle_default{
118
 -(void)testTitle_default{
123
-	__unused RNNNavigationController* nav = [self createNavigationController];
124
-
125
 	[self.uut viewWillAppear:false];
119
 	[self.uut viewWillAppear:false];
126
 	XCTAssertNil(self.uut.navigationItem.title);
120
 	XCTAssertNil(self.uut.navigationItem.title);
127
 }
121
 }
143
 	XCTAssertTrue([self.uut.view.backgroundColor isEqual:expectedColor]);
137
 	XCTAssertTrue([self.uut.view.backgroundColor isEqual:expectedColor]);
144
 }
138
 }
145
 
139
 
146
--(void)testPopGestureEnabled_true{
147
-	NSNumber* popGestureEnabled = @(1);
148
-	self.options.popGesture = popGestureEnabled;
149
-	__unused RNNNavigationController* nav = [self createNavigationController];
150
-	[self.uut viewWillAppear:false];
151
-	XCTAssertTrue(self.uut.navigationController.interactivePopGestureRecognizer.enabled);
152
-}
153
-
154
--(void)testPopGestureEnabled_false{
155
-	NSNumber* popGestureEnabled = @(0);
156
-	self.options.popGesture = popGestureEnabled;
157
-	__unused RNNNavigationController* nav = [self createNavigationController];
158
-	
159
-	[self.uut viewWillAppear:false];
160
-	XCTAssertFalse(self.uut.navigationController.interactivePopGestureRecognizer.enabled);
161
-}
162
-
163
 -(void)testTopBarTextFontFamily_validFont{
140
 -(void)testTopBarTextFontFamily_validFont{
164
 	NSString* inputFont = @"HelveticaNeue";
141
 	NSString* inputFont = @"HelveticaNeue";
165
 	__unused RNNNavigationController* nav = [self createNavigationController];
142
 	__unused RNNNavigationController* nav = [self createNavigationController];
219
 }
196
 }
220
 
197
 
221
 -(void)testTopBarLargeTitle_default {
198
 -(void)testTopBarLargeTitle_default {
222
-	__unused RNNNavigationController* nav = [self createNavigationController];
223
 	[self.uut viewWillAppear:false];
199
 	[self.uut viewWillAppear:false];
224
 	
200
 	
225
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode,  UINavigationItemLargeTitleDisplayModeNever);
201
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode,  UINavigationItemLargeTitleDisplayModeNever);
226
 }
202
 }
227
 -(void)testTopBarLargeTitle_true {
203
 -(void)testTopBarLargeTitle_true {
228
 	self.options.topBar.largeTitle.visible = @(1);
204
 	self.options.topBar.largeTitle.visible = @(1);
229
-	__unused RNNNavigationController* nav = [self createNavigationController];
230
 	[self.uut viewWillAppear:false];
205
 	[self.uut viewWillAppear:false];
231
 	
206
 	
232
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeAlways);
207
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeAlways);
233
 }
208
 }
234
 -(void)testTopBarLargeTitle_false {
209
 -(void)testTopBarLargeTitle_false {
235
 	self.options.topBar.largeTitle.visible  = @(0);
210
 	self.options.topBar.largeTitle.visible  = @(0);
236
-	__unused RNNNavigationController* nav = [self createNavigationController];
237
 	[self.uut viewWillAppear:false];
211
 	[self.uut viewWillAppear:false];
238
 	
212
 	
239
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeNever);
213
 	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeNever);
246
 	__unused RNNNavigationController* nav = [self createNavigationController];
220
 	__unused RNNNavigationController* nav = [self createNavigationController];
247
 	[self.uut viewWillAppear:false];
221
 	[self.uut viewWillAppear:false];
248
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
222
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
223
+
249
 	XCTAssertTrue([self.uut.navigationController.navigationBar.largeTitleTextAttributes[@"NSFont"] isEqual:expectedFont]);
224
 	XCTAssertTrue([self.uut.navigationController.navigationBar.largeTitleTextAttributes[@"NSFont"] isEqual:expectedFont]);
250
 }
225
 }
251
 
226
 
482
 
457
 
483
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
458
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
484
 	__unused RNNNavigationController* nav = [self createNavigationController];
459
 	__unused RNNNavigationController* nav = [self createNavigationController];
460
+
485
 	[self.uut viewWillAppear:false];
461
 	[self.uut viewWillAppear:false];
486
 
462
 
487
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
463
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
513
 -(void)testStatusBarBlurOn {
489
 -(void)testStatusBarBlurOn {
514
 	NSNumber* statusBarBlurInput = @(1);
490
 	NSNumber* statusBarBlurInput = @(1);
515
 	self.options.statusBar.blur = statusBarBlurInput;
491
 	self.options.statusBar.blur = statusBarBlurInput;
516
-	__unused RNNNavigationController* nav = [self createNavigationController];
517
 	[self.uut viewWillAppear:false];
492
 	[self.uut viewWillAppear:false];
518
 	XCTAssertNotNil([self.uut.view viewWithTag:BLUR_STATUS_TAG]);
493
 	XCTAssertNotNil([self.uut.view viewWithTag:BLUR_STATUS_TAG]);
519
 }
494
 }
521
 -(void)testStatusBarBlurOff {
496
 -(void)testStatusBarBlurOff {
522
 	NSNumber* statusBarBlurInput = @(0);
497
 	NSNumber* statusBarBlurInput = @(0);
523
 	self.options.statusBar.blur = statusBarBlurInput;
498
 	self.options.statusBar.blur = statusBarBlurInput;
524
-	__unused RNNNavigationController* nav = [self createNavigationController];
525
 	[self.uut viewWillAppear:false];
499
 	[self.uut viewWillAppear:false];
526
 	XCTAssertNil([self.uut.view viewWithTag:BLUR_STATUS_TAG]);
500
 	XCTAssertNil([self.uut.view viewWithTag:BLUR_STATUS_TAG]);
527
 }
501
 }
528
 
502
 
529
 - (void)testTabBarHidden_default {
503
 - (void)testTabBarHidden_default {
530
-	__unused RNNNavigationController* nav = [self createNavigationController];
531
 	[self.uut viewWillAppear:false];
504
 	[self.uut viewWillAppear:false];
532
 
505
 
533
 	XCTAssertFalse([self.uut hidesBottomBarWhenPushed]);
506
 	XCTAssertFalse([self.uut hidesBottomBarWhenPushed]);
536
 
509
 
537
 - (void)testTabBarHidden_true {
510
 - (void)testTabBarHidden_true {
538
 	self.options.bottomTabs.visible = @(0);
511
 	self.options.bottomTabs.visible = @(0);
539
-	__unused RNNNavigationController* nav = [self createNavigationController];
540
 	[self.uut viewWillAppear:false];
512
 	[self.uut viewWillAppear:false];
541
 
513
 
542
 	XCTAssertTrue([self.uut hidesBottomBarWhenPushed]);
514
 	XCTAssertTrue([self.uut hidesBottomBarWhenPushed]);
544
 
516
 
545
 - (void)testTabBarHidden_false {
517
 - (void)testTabBarHidden_false {
546
 	self.options.bottomTabs.visible = @(1);
518
 	self.options.bottomTabs.visible = @(1);
547
-	__unused RNNNavigationController* nav = [self createNavigationController];
548
 	[self.uut viewWillAppear:false];
519
 	[self.uut viewWillAppear:false];
549
 
520
 
550
 	XCTAssertFalse([self.uut hidesBottomBarWhenPushed]);
521
 	XCTAssertFalse([self.uut hidesBottomBarWhenPushed]);
575
 -(void)testBackgroundImage {
546
 -(void)testBackgroundImage {
576
 	UIImage* backgroundImage = [[UIImage alloc] init];
547
 	UIImage* backgroundImage = [[UIImage alloc] init];
577
 	self.options.backgroundImage = backgroundImage;
548
 	self.options.backgroundImage = backgroundImage;
578
-	__unused RNNNavigationController* nav = [self createNavigationController];
579
 	[self.uut viewWillAppear:false];
549
 	[self.uut viewWillAppear:false];
580
 
550
 
581
 	XCTAssertTrue([[(UIImageView*)self.uut.view.subviews[0] image] isEqual:backgroundImage]);
551
 	XCTAssertTrue([[(UIImageView*)self.uut.view.subviews[0] image] isEqual:backgroundImage]);
582
 }
552
 }
583
 
553
 
584
--(void)testRootBackgroundImage {
585
-	UIImage* rootBackgroundImage = [[UIImage alloc] init];
586
-	self.options.rootBackgroundImage = rootBackgroundImage;
587
-	__unused RNNNavigationController* nav = [self createNavigationController];
588
-	[self.uut viewWillAppear:false];
589
-	XCTAssertTrue([[(UIImageView*)self.uut.navigationController.view.subviews[0] image] isEqual:rootBackgroundImage]);
590
-}
591
-
592
 -(void)testTopBarDrawUnder_true {
554
 -(void)testTopBarDrawUnder_true {
593
 	self.options.topBar.drawBehind = @(1);
555
 	self.options.topBar.drawBehind = @(1);
594
-	__unused RNNNavigationController* nav = [self createNavigationController];
595
 	[self.uut viewWillAppear:false];
556
 	[self.uut viewWillAppear:false];
596
 
557
 
597
 	XCTAssertTrue(self.uut.edgesForExtendedLayout & UIRectEdgeTop);
558
 	XCTAssertTrue(self.uut.edgesForExtendedLayout & UIRectEdgeTop);
599
 
560
 
600
 -(void)testTopBarDrawUnder_false {
561
 -(void)testTopBarDrawUnder_false {
601
 	self.options.topBar.drawBehind = @(0);
562
 	self.options.topBar.drawBehind = @(0);
602
-	__unused RNNNavigationController* nav = [self createNavigationController];
603
 	[self.uut viewWillAppear:false];
563
 	[self.uut viewWillAppear:false];
604
 
564
 
605
 	XCTAssertFalse(self.uut.edgesForExtendedLayout & UIRectEdgeTop);
565
 	XCTAssertFalse(self.uut.edgesForExtendedLayout & UIRectEdgeTop);
607
 
567
 
608
 -(void)testBottomTabsDrawUnder_true {
568
 -(void)testBottomTabsDrawUnder_true {
609
 	self.options.bottomTabs.drawBehind = @(1);
569
 	self.options.bottomTabs.drawBehind = @(1);
610
-	__unused RNNNavigationController* nav = [self createNavigationController];
611
 	[self.uut viewWillAppear:false];
570
 	[self.uut viewWillAppear:false];
612
 
571
 
613
 	XCTAssertTrue(self.uut.edgesForExtendedLayout & UIRectEdgeBottom);
572
 	XCTAssertTrue(self.uut.edgesForExtendedLayout & UIRectEdgeBottom);
615
 
574
 
616
 -(void)testBottomTabsDrawUnder_false {
575
 -(void)testBottomTabsDrawUnder_false {
617
 	self.options.bottomTabs.drawBehind = @(0);
576
 	self.options.bottomTabs.drawBehind = @(0);
618
-	__unused RNNNavigationController* nav = [self createNavigationController];
619
 	[self.uut viewWillAppear:false];
577
 	[self.uut viewWillAppear:false];
620
 
578
 
621
 	XCTAssertFalse(self.uut.edgesForExtendedLayout & UIRectEdgeBottom);
579
 	XCTAssertFalse(self.uut.edgesForExtendedLayout & UIRectEdgeBottom);
714
 	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
672
 	XCTAssertTrue([attributes[@"NSFont"] isEqual:expectedFont]);
715
 }
673
 }
716
 
674
 
717
-- (void)testTopBarBackgroundClipToBounds_true {
718
-	self.options.topBar.background.clipToBounds = @(1);
719
-	__unused RNNNavigationController* nav = [self createNavigationController];
720
-	[self.uut viewWillAppear:false];
721
-
722
-	XCTAssertTrue(self.uut.navigationController.navigationBar.clipsToBounds);
723
-}
724
-
725
-- (void)testTopBarBackgroundClipToBounds_false {
726
-	__unused RNNNavigationController* nav = [self createNavigationController];
727
-	[self.uut viewWillAppear:false];
728
-
729
-	XCTAssertFalse(self.uut.navigationController.navigationBar.clipsToBounds);
730
-}
731
-
732
 - (void)testWillMoveToParent_shouldPassOptionsToParent {
675
 - (void)testWillMoveToParent_shouldPassOptionsToParent {
733
 	__unused RNNNavigationController* nav = [self createNavigationController];
676
 	__unused RNNNavigationController* nav = [self createNavigationController];
734
-	self.uut.presenter.options.topBar.visible = @(0);
677
+	self.uut.options.topBar.visible = @(0);
735
 	[self.uut willMoveToParentViewController:nav];
678
 	[self.uut willMoveToParentViewController:nav];
736
 	XCTAssertTrue(nav.navigationBarHidden);
679
 	XCTAssertTrue(nav.navigationBarHidden);
737
 }
680
 }
738
 
681
 
739
 - (RNNNavigationController *)createNavigationController {
682
 - (RNNNavigationController *)createNavigationController {
740
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
683
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
741
-	nav.presenter = [[RNNNavigationControllerPresenter alloc] initWithOptions:[[RNNNavigationOptions alloc] initWithDict:@{}]];
684
+	nav.options = [[RNNNavigationOptions alloc] initWithDict:@{}];
685
+	nav.presenter = [[RNNNavigationControllerPresenter alloc] init];
742
 	
686
 	
743
 	return nav;
687
 	return nav;
744
 }
688
 }