Browse Source

SetRoot wait for render (#4688)

* Layout changes

* WIP

* Revert "Layout changes"

This reverts commit 4da8cfbd12.

* Clean topBar.component and topBar.background.component when not needed

* Move custom components login from viewController to presenters

* Change waitForRender and enabled property from primitive bool to Bool object

* Fix ios unit tests

* Add unit tests

* Remove RNNReactView observer when view ready

* Load react components from component manager

* Remove createCustomReactView duplication

* Handle render children in each Layout

* Wait for navigation presenter components render, refactor RNNTitleViewHelper

* Fix unit tests

* Add waitForRender for custom react components

* Fixes e2e
Yogev Ben David 5 years ago
parent
commit
5abea28c53
No account linked to committer's email address
52 changed files with 621 additions and 305 deletions
  1. 12
    0
      lib/ios/RNNBasePresenter.m
  2. 5
    1
      lib/ios/RNNBridgeManager.m
  3. 30
    24
      lib/ios/RNNCommandsHandler.m
  4. 1
    0
      lib/ios/RNNComponentOptions.h
  5. 1
    0
      lib/ios/RNNComponentOptions.m
  6. 5
    2
      lib/ios/RNNControllerFactory.h
  7. 10
    17
      lib/ios/RNNControllerFactory.m
  8. 5
    1
      lib/ios/RNNLayoutProtocol.h
  9. 0
    7
      lib/ios/RNNLeafProtocol.h
  10. 2
    2
      lib/ios/RNNModalManager.m
  11. 2
    1
      lib/ios/RNNNavigationButtons.h
  12. 9
    5
      lib/ios/RNNNavigationButtons.m
  13. 3
    0
      lib/ios/RNNNavigationController.h
  14. 26
    1
      lib/ios/RNNNavigationController.m
  15. 6
    0
      lib/ios/RNNNavigationControllerPresenter.h
  16. 98
    0
      lib/ios/RNNNavigationControllerPresenter.m
  17. 2
    1
      lib/ios/RNNParentProtocol.h
  18. 17
    0
      lib/ios/RNNReactComponentManager.h
  19. 52
    0
      lib/ios/RNNReactComponentManager.m
  20. 0
    6
      lib/ios/RNNReactRootView.h
  21. 0
    16
      lib/ios/RNNReactRootView.m
  22. 10
    18
      lib/ios/RNNReactRootViewCreator.m
  23. 5
    0
      lib/ios/RNNReactView.h
  24. 13
    5
      lib/ios/RNNReactView.m
  25. 24
    135
      lib/ios/RNNRootViewController.m
  26. 3
    2
      lib/ios/RNNRootViewCreator.h
  27. 2
    2
      lib/ios/RNNScreenTransition.h
  28. 2
    3
      lib/ios/RNNScreenTransition.m
  29. 1
    0
      lib/ios/RNNSideMenuChildVC.h
  30. 4
    0
      lib/ios/RNNSideMenuChildVC.m
  31. 1
    0
      lib/ios/RNNSideMenuController.h
  32. 22
    0
      lib/ios/RNNSideMenuController.m
  33. 20
    0
      lib/ios/RNNSplitViewController.m
  34. 20
    0
      lib/ios/RNNTabBarController.m
  35. 2
    0
      lib/ios/RNNTitleViewHelper.h
  36. 8
    7
      lib/ios/RNNTitleViewHelper.m
  37. 0
    1
      lib/ios/RNNTopTabOptions.m
  38. 1
    1
      lib/ios/RNNTopTabsViewController.h
  39. 21
    0
      lib/ios/RNNTopTabsViewController.m
  40. 2
    0
      lib/ios/RNNTransitionsOptions.h
  41. 2
    0
      lib/ios/RNNTransitionsOptions.m
  42. 5
    2
      lib/ios/RNNViewControllerPresenter.h
  43. 94
    3
      lib/ios/RNNViewControllerPresenter.m
  44. 8
    8
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  45. 38
    11
      lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m
  46. 11
    11
      lib/ios/ReactNativeNavigationTests/RNNControllerFactoryTest.m
  47. 6
    4
      lib/ios/ReactNativeNavigationTests/RNNNavigationControllerTest.m
  48. 5
    5
      lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m
  49. 1
    1
      lib/ios/ReactNativeNavigationTests/RNNTestRootViewCreator.m
  50. 1
    1
      lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m
  51. 1
    0
      lib/ios/UIViewController+RNNOptions.m
  52. 2
    1
      playground/src/app.js

+ 12
- 0
lib/ios/RNNBasePresenter.m View File

1
 #import "RNNBasePresenter.h"
1
 #import "RNNBasePresenter.h"
2
 #import "UIViewController+RNNOptions.h"
2
 #import "UIViewController+RNNOptions.h"
3
 #import "RNNTabBarItemCreator.h"
3
 #import "RNNTabBarItemCreator.h"
4
+#import "RNNReactComponentManager.h"
5
+
6
+@interface RNNBasePresenter ()
7
+@property (nonatomic, strong) RNNReactComponentManager* componentManager;
8
+@end
9
+
4
 
10
 
5
 @implementation RNNBasePresenter
11
 @implementation RNNBasePresenter
6
 
12
 
13
+- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager {
14
+	self = [super init];
15
+	self.componentManager = componentManager;
16
+	return self;
17
+}
18
+
7
 - (void)bindViewController:(UIViewController *)bindedViewController {
19
 - (void)bindViewController:(UIViewController *)bindedViewController {
8
 	_bindedViewController = bindedViewController;
20
 	_bindedViewController = bindedViewController;
9
 }
21
 }

+ 5
- 1
lib/ios/RNNBridgeManager.m View File

8
 #import "RNNBridgeModule.h"
8
 #import "RNNBridgeModule.h"
9
 #import "RNNRootViewCreator.h"
9
 #import "RNNRootViewCreator.h"
10
 #import "RNNReactRootViewCreator.h"
10
 #import "RNNReactRootViewCreator.h"
11
+#import "RNNReactComponentManager.h"
11
 
12
 
12
 @interface RNNBridgeManager() <RCTBridgeDelegate>
13
 @interface RNNBridgeManager() <RCTBridgeDelegate>
13
 
14
 
14
 @property (nonatomic, strong, readwrite) RCTBridge *bridge;
15
 @property (nonatomic, strong, readwrite) RCTBridge *bridge;
15
 @property (nonatomic, strong, readwrite) RNNStore *store;
16
 @property (nonatomic, strong, readwrite) RNNStore *store;
17
+@property (nonatomic, strong, readwrite) RNNReactComponentManager *componentManager;
16
 
18
 
17
 @end
19
 @end
18
 
20
 
77
 	RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
79
 	RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
78
 
80
 
79
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
81
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
80
-	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter andBridge:bridge];
82
+	_componentManager = [[RNNReactComponentManager alloc] initWithCreator:rootViewCreator];
83
+	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentManager:_componentManager andBridge:bridge];
81
 	
84
 	
82
 	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:[RNNOverlayManager new] mainWindow:_mainWindow];
85
 	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:[RNNOverlayManager new] mainWindow:_mainWindow];
83
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
86
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
89
 
92
 
90
 - (void)onJavaScriptWillLoad {
93
 - (void)onJavaScriptWillLoad {
91
 	[_store clean];
94
 	[_store clean];
95
+	[_componentManager clean];
92
 }
96
 }
93
 
97
 
94
 - (void)onJavaScriptLoaded {
98
 - (void)onJavaScriptLoaded {

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

58
 	[_modalManager dismissAllModalsAnimated:NO];
58
 	[_modalManager dismissAllModalsAnimated:NO];
59
 	[_store removeAllComponentsFromWindow:_mainWindow];
59
 	[_store removeAllComponentsFromWindow:_mainWindow];
60
 	
60
 	
61
-	UIViewController *vc = [_controllerFactory createLayout:layout[@"root"] saveToStore:_store];
61
+	UIViewController<RNNLayoutProtocol> *vc = [_controllerFactory createLayout:layout[@"root"]];
62
 	
62
 	
63
-	_mainWindow.rootViewController = vc;
64
-	
65
-	[_eventEmitter sendOnNavigationCommandCompletion:setRoot params:@{@"layout": layout}];
66
-	completion();
63
+	[vc renderTreeAndWait:[vc.resolveOptions.animations.setRoot.waitForRender getWithDefaultValue:NO] perform:^{
64
+		_mainWindow.rootViewController = vc;
65
+		[_eventEmitter sendOnNavigationCommandCompletion:setRoot params:@{@"layout": layout}];
66
+		completion() ;
67
+	}];
67
 }
68
 }
68
 
69
 
69
 - (void)mergeOptions:(NSString*)componentId options:(NSDictionary*)mergeOptions completion:(RNNTransitionCompletionBlock)completion {
70
 - (void)mergeOptions:(NSString*)componentId options:(NSDictionary*)mergeOptions completion:(RNNTransitionCompletionBlock)completion {
96
 - (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
97
 - (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
97
 	[self assertReady];
98
 	[self assertReady];
98
 	
99
 	
99
-	UIViewController<RNNLayoutProtocol> *newVc = [_controllerFactory createLayout:layout saveToStore:_store];
100
+	UIViewController<RNNLayoutProtocol> *newVc = [_controllerFactory createLayout:layout];
100
 	UIViewController *fromVC = [_store findComponentForId:componentId];
101
 	UIViewController *fromVC = [_store findComponentForId:componentId];
101
 	
102
 	
102
 	if ([[newVc.resolveOptions.preview.reactTag getWithDefaultValue:@(0)] floatValue] > 0) {
103
 	if ([[newVc.resolveOptions.preview.reactTag getWithDefaultValue:@(0)] floatValue] > 0) {
141
 		}
142
 		}
142
 	} else {
143
 	} else {
143
 		id animationDelegate = (newVc.resolveOptions.animations.push.hasCustomAnimation || newVc.getCurrentLeaf.isCustomTransitioned) ? newVc : nil;
144
 		id animationDelegate = (newVc.resolveOptions.animations.push.hasCustomAnimation || newVc.getCurrentLeaf.isCustomTransitioned) ? newVc : nil;
144
-		[newVc.getCurrentLeaf waitForReactViewRender:(newVc.resolveOptions.animations.push.waitForRender || animationDelegate) perform:^{
145
-			[_stackManager push:newVc onTop:fromVC animated:newVc.resolveOptions.animations.push.enable animationDelegate:animationDelegate completion:^{
145
+		[newVc renderTreeAndWait:([newVc.resolveOptions.animations.push.waitForRender getWithDefaultValue:NO] || animationDelegate) perform:^{
146
+			[_stackManager push:newVc onTop:fromVC animated:[newVc.resolveOptions.animations.push.enable getWithDefaultValue:YES] animationDelegate:animationDelegate completion:^{
146
 				[_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
147
 				[_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
147
 				completion();
148
 				completion();
148
 			} rejection:rejection];
149
 			} rejection:rejection];
153
 - (void)setStackRoot:(NSString*)componentId children:(NSArray*)children completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
154
 - (void)setStackRoot:(NSString*)componentId children:(NSArray*)children completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
154
 	[self assertReady];
155
 	[self assertReady];
155
 	
156
 	
156
- 	NSArray<RNNLayoutProtocol> *childViewControllers = [_controllerFactory createChildrenLayout:children saveToStore:_store];
157
+ 	NSArray<RNNLayoutProtocol> *childViewControllers = [_controllerFactory createChildrenLayout:children];
158
+	for (UIViewController<RNNLayoutProtocol>* viewController in childViewControllers) {
159
+		[viewController renderTreeAndWait:NO perform:nil];
160
+	}
157
 	RNNNavigationOptions* options = [childViewControllers.lastObject getCurrentChild].resolveOptions;
161
 	RNNNavigationOptions* options = [childViewControllers.lastObject getCurrentChild].resolveOptions;
158
 	UIViewController *fromVC = [_store findComponentForId:componentId];
162
 	UIViewController *fromVC = [_store findComponentForId:componentId];
159
 	__weak typeof(RNNEventEmitter*) weakEventEmitter = _eventEmitter;
163
 	__weak typeof(RNNEventEmitter*) weakEventEmitter = _eventEmitter;
160
-	[_stackManager setStackChildren:childViewControllers fromViewController:fromVC animated:options.animations.setStackRoot.enable completion:^{
164
+	[_stackManager setStackChildren:childViewControllers fromViewController:fromVC animated:[options.animations.setStackRoot.enable getWithDefaultValue:YES] completion:^{
161
 		[weakEventEmitter sendOnNavigationCommandCompletion:setStackRoot params:@{@"componentId": componentId}];
165
 		[weakEventEmitter sendOnNavigationCommandCompletion:setStackRoot params:@{@"componentId": componentId}];
162
 		completion();
166
 		completion();
163
 	} rejection:rejection];
167
 	} rejection:rejection];
181
 	} else {
185
 	} else {
182
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
186
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
183
 		[vcs removeObject:vc];
187
 		[vcs removeObject:vc];
184
-		[nvc setViewControllers:vcs animated:vc.resolveOptions.animations.pop.enable];
188
+		[nvc setViewControllers:vcs animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES]];
185
 	}
189
 	}
186
 	
190
 	
187
-	[_stackManager pop:vc animated:vc.resolveOptions.animations.pop.enable completion:^{
191
+	[_stackManager pop:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^{
188
 		[_store removeComponent:componentId];
192
 		[_store removeComponent:componentId];
189
 		[_eventEmitter sendOnNavigationCommandCompletion:pop params:@{@"componentId": componentId}];
193
 		[_eventEmitter sendOnNavigationCommandCompletion:pop params:@{@"componentId": componentId}];
190
 		completion();
194
 		completion();
197
 	RNNNavigationOptions *options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
201
 	RNNNavigationOptions *options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
198
 	[vc overrideOptions:options];
202
 	[vc overrideOptions:options];
199
 	
203
 	
200
-	[_stackManager popTo:vc animated:vc.resolveOptions.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
204
+	[_stackManager popTo:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
201
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
205
 		[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
202
 		[self removePopedViewControllers:poppedViewControllers];
206
 		[self removePopedViewControllers:poppedViewControllers];
203
 		completion();
207
 		completion();
216
 		completion();
220
 		completion();
217
 	}];
221
 	}];
218
 	
222
 	
219
-	[_stackManager popToRoot:vc animated:vc.resolveOptions.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
223
+	[_stackManager popToRoot:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
220
 		[self removePopedViewControllers:poppedViewControllers];
224
 		[self removePopedViewControllers:poppedViewControllers];
221
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
225
 	} rejection:^(NSString *code, NSString *message, NSError *error) {
222
 		
226
 		
228
 - (void)showModal:(NSDictionary*)layout completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
232
 - (void)showModal:(NSDictionary*)layout completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
229
 	[self assertReady];
233
 	[self assertReady];
230
 	
234
 	
231
-	UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayout:layout saveToStore:_store];
235
+	UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayout:layout];
232
 	
236
 	
233
-	[newVc.getCurrentLeaf waitForReactViewRender:newVc.getCurrentLeaf.resolveOptions.animations.showModal.waitForRender perform:^{
234
-		[_modalManager showModal:newVc animated:newVc.getCurrentChild.resolveOptions.animations.showModal.enable hasCustomAnimation:newVc.getCurrentChild.resolveOptions.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
237
+	[newVc renderTreeAndWait:[newVc.getCurrentLeaf.resolveOptions.animations.showModal.waitForRender getWithDefaultValue:NO] perform:^{
238
+		[_modalManager showModal:newVc animated:[newVc.getCurrentChild.resolveOptions.animations.showModal.enable getWithDefaultValue:YES] hasCustomAnimation:newVc.getCurrentChild.resolveOptions.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
235
 			[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
239
 			[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
236
 			completion(componentId);
240
 			completion(componentId);
237
 		}];
241
 		}];
272
 		completion();
276
 		completion();
273
 	}];
277
 	}];
274
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
278
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
275
-	[_modalManager dismissAllModalsAnimated:options.animations.dismissModal.enable];
279
+	[_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES]];
276
 	
280
 	
277
 	[CATransaction commit];
281
 	[CATransaction commit];
278
 }
282
 }
280
 - (void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion {
284
 - (void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion {
281
 	[self assertReady];
285
 	[self assertReady];
282
 	
286
 	
283
-	UIViewController<RNNParentProtocol>* overlayVC = [_controllerFactory createLayout:layout saveToStore:_store];
284
-	UIWindow* overlayWindow = [[RNNOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
285
-	overlayWindow.rootViewController = overlayVC;
286
-	[_overlayManager showOverlayWindow:overlayWindow];
287
-	[_eventEmitter sendOnNavigationCommandCompletion:showOverlay params:@{@"layout": layout}];
288
-	completion();
287
+	UIViewController<RNNParentProtocol>* overlayVC = [_controllerFactory createLayout:layout];
288
+	[overlayVC renderTreeAndWait:[overlayVC.options.animations.showOverlay.waitForRender getWithDefaultValue:NO] perform:^{
289
+		UIWindow* overlayWindow = [[RNNOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
290
+		overlayWindow.rootViewController = overlayVC;
291
+		[_overlayManager showOverlayWindow:overlayWindow];
292
+		[_eventEmitter sendOnNavigationCommandCompletion:showOverlay params:@{@"layout": layout}];
293
+		completion();
294
+	}];
289
 }
295
 }
290
 
296
 
291
 - (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject {
297
 - (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject {

+ 1
- 0
lib/ios/RNNComponentOptions.h View File

5
 @property (nonatomic, strong) Text* name;
5
 @property (nonatomic, strong) Text* name;
6
 @property (nonatomic, strong) Text* componentId;
6
 @property (nonatomic, strong) Text* componentId;
7
 @property (nonatomic, strong) Text* alignment;
7
 @property (nonatomic, strong) Text* alignment;
8
+@property (nonatomic, strong) Bool* waitForRender;
8
 
9
 
9
 @end
10
 @end

+ 1
- 0
lib/ios/RNNComponentOptions.m View File

8
 	self.name = [TextParser parse:dict key:@"name"];
8
 	self.name = [TextParser parse:dict key:@"name"];
9
 	self.componentId = [TextParser parse:dict key:@"componentId"];
9
 	self.componentId = [TextParser parse:dict key:@"componentId"];
10
 	self.alignment = [TextParser parse:dict key:@"alignment"];
10
 	self.alignment = [TextParser parse:dict key:@"alignment"];
11
+	self.waitForRender = [BoolParser parse:dict key:@"waitForRender"];
11
 	
12
 	
12
 	return self;
13
 	return self;
13
 }
14
 }

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

5
 #import "RNNStore.h"
5
 #import "RNNStore.h"
6
 #import "RNNEventEmitter.h"
6
 #import "RNNEventEmitter.h"
7
 #import "RNNParentProtocol.h"
7
 #import "RNNParentProtocol.h"
8
+#import "RNNReactComponentManager.h"
8
 
9
 
9
 @interface RNNControllerFactory : NSObject
10
 @interface RNNControllerFactory : NSObject
10
 
11
 
11
 -(instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
12
 -(instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
12
 						  eventEmitter:(RNNEventEmitter*)eventEmitter
13
 						  eventEmitter:(RNNEventEmitter*)eventEmitter
14
+								 store:(RNNStore *)store
15
+					  componentManager:(RNNReactComponentManager *)componentManager
13
 							 andBridge:(RCTBridge*)bridge;
16
 							 andBridge:(RCTBridge*)bridge;
14
 
17
 
15
-- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout saveToStore:(RNNStore *)store;
18
+- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout;
16
 
19
 
17
-- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children saveToStore:(RNNStore *)store;
20
+- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children;
18
 
21
 
19
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
22
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
20
 
23
 

+ 10
- 17
lib/ios/RNNControllerFactory.m View File

20
 	id<RNNRootViewCreator> _creator;
20
 	id<RNNRootViewCreator> _creator;
21
 	RNNStore *_store;
21
 	RNNStore *_store;
22
 	RCTBridge *_bridge;
22
 	RCTBridge *_bridge;
23
+	RNNReactComponentManager* _componentManager;
23
 }
24
 }
24
 
25
 
25
 # pragma mark public
26
 # pragma mark public
27
 
28
 
28
 - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
29
 - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
29
 						   eventEmitter:(RNNEventEmitter*)eventEmitter
30
 						   eventEmitter:(RNNEventEmitter*)eventEmitter
31
+								  store:(RNNStore *)store
32
+					   componentManager:(RNNReactComponentManager *)componentManager
30
 							  andBridge:(RCTBridge *)bridge {
33
 							  andBridge:(RCTBridge *)bridge {
31
 	
34
 	
32
 	self = [super init];
35
 	self = [super init];
34
 	_creator = creator;
37
 	_creator = creator;
35
 	_eventEmitter = eventEmitter;
38
 	_eventEmitter = eventEmitter;
36
 	_bridge = bridge;
39
 	_bridge = bridge;
40
+	_store = store;
41
+	_componentManager = componentManager;
37
 	
42
 	
38
 	return self;
43
 	return self;
39
 }
44
 }
40
 
45
 
41
-- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout saveToStore:(RNNStore *)store {
42
-	_store = store;
46
+- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout {
43
 	UIViewController<RNNParentProtocol>* layoutViewController = [self fromTree:layout];
47
 	UIViewController<RNNParentProtocol>* layoutViewController = [self fromTree:layout];
44
-	_store = nil;
45
 	return layoutViewController;
48
 	return layoutViewController;
46
 }
49
 }
47
 
50
 
48
-- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children saveToStore:(RNNStore *)store {
49
-	_store = store;
51
+- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children {
50
 	NSMutableArray<RNNLayoutProtocol>* childViewControllers = [NSMutableArray<RNNLayoutProtocol> new];
52
 	NSMutableArray<RNNLayoutProtocol>* childViewControllers = [NSMutableArray<RNNLayoutProtocol> new];
51
 	for (NSDictionary* layout in children) {
53
 	for (NSDictionary* layout in children) {
52
 		[childViewControllers addObject:[self fromTree:layout]];
54
 		[childViewControllers addObject:[self fromTree:layout]];
53
 	}
55
 	}
54
-	_store = nil;
55
 	return childViewControllers;
56
 	return childViewControllers;
56
 }
57
 }
57
 
58
 
114
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
115
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
115
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
116
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
116
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
117
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
117
-	
118
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
119
-
118
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentManager:_componentManager];
120
 	
119
 	
121
 	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];
120
 	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];
122
 	
121
 	
123
-	if (!component.isExternalViewController) {
124
-		CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
125
-		[_bridge.uiManager setAvailableSize:availableSize forRootView:component.view];
126
-	}
127
-	
128
 	return (UIViewController<RNNParentProtocol> *)component;
122
 	return (UIViewController<RNNParentProtocol> *)component;
129
 }
123
 }
130
 
124
 
143
 
137
 
144
 
138
 
145
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
139
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
146
-	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] init];
147
-	
140
+	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentManager:_componentManager];
148
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
141
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
149
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
142
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
150
 	
143
 	
151
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
144
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
152
 	
145
 	
153
-	RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
146
+	RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo creator:_creator childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
154
 	
147
 	
155
 	return stack;
148
 	return stack;
156
 }
149
 }

+ 5
- 1
lib/ios/RNNLayoutProtocol.h View File

1
 #import "RNNLayoutInfo.h"
1
 #import "RNNLayoutInfo.h"
2
-#import "RNNViewControllerPresenter.h"
3
 #import "RNNLeafProtocol.h"
2
 #import "RNNLeafProtocol.h"
3
+#import "RNNBasePresenter.h"
4
+
5
+typedef void (^RNNReactViewReadyCompletionBlock)(void);
4
 
6
 
5
 @protocol RNNLayoutProtocol <NSObject, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
7
 @protocol RNNLayoutProtocol <NSObject, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
6
 
8
 
11
 @property (nonatomic, strong) RNNNavigationOptions* options;
13
 @property (nonatomic, strong) RNNNavigationOptions* options;
12
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
14
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
13
 
15
 
16
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;
17
+
14
 - (UIViewController<RNNLayoutProtocol> *)getCurrentChild;
18
 - (UIViewController<RNNLayoutProtocol> *)getCurrentChild;
15
 
19
 
16
 - (UIViewController<RNNLeafProtocol, RNNLayoutProtocol> *)getCurrentLeaf;
20
 - (UIViewController<RNNLeafProtocol, RNNLayoutProtocol> *)getCurrentLeaf;

+ 0
- 7
lib/ios/RNNLeafProtocol.h View File

1
-#import "RNNRootViewCreator.h"
2
-
3
-typedef void (^RNNReactViewReadyCompletionBlock)(void);
4
 
1
 
5
 @protocol RNNLeafProtocol <NSObject>
2
 @protocol RNNLeafProtocol <NSObject>
6
 
3
 
7
-- (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;
8
-
9
 - (void)bindViewController:(UIViewController *)viewController;
4
 - (void)bindViewController:(UIViewController *)viewController;
10
 
5
 
11
 - (BOOL)isCustomTransitioned;
6
 - (BOOL)isCustomTransitioned;
12
 
7
 
13
-- (id<RNNRootViewCreator>)creator;
14
-
15
 @end
8
 @end

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

73
 	}
73
 	}
74
 
74
 
75
 	if (modalToDismiss == topPresentedVC || [[topPresentedVC childViewControllers] containsObject:modalToDismiss]) {
75
 	if (modalToDismiss == topPresentedVC || [[topPresentedVC childViewControllers] containsObject:modalToDismiss]) {
76
-		[modalToDismiss dismissViewControllerAnimated:options.animations.dismissModal.enable completion:^{
76
+		[modalToDismiss dismissViewControllerAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:^{
77
 			[_pendingModalIdsToDismiss removeObject:modalToDismiss];
77
 			[_pendingModalIdsToDismiss removeObject:modalToDismiss];
78
 			if (modalToDismiss.view) {
78
 			if (modalToDismiss.view) {
79
 				[self dismissedModal:modalToDismiss];
79
 				[self dismissedModal:modalToDismiss];
88
 	} else {
88
 	} else {
89
 		[modalToDismiss.view removeFromSuperview];
89
 		[modalToDismiss.view removeFromSuperview];
90
 		modalToDismiss.view = nil;
90
 		modalToDismiss.view = nil;
91
-		modalToDismiss.getCurrentChild.resolveOptions.animations.dismissModal.enable = NO;
91
+		modalToDismiss.getCurrentChild.resolveOptions.animations.dismissModal.enable = [[Bool alloc] initWithBOOL:NO];
92
 		[self dismissedModal:modalToDismiss];
92
 		[self dismissedModal:modalToDismiss];
93
 		
93
 		
94
 		if (completion) {
94
 		if (completion) {

+ 2
- 1
lib/ios/RNNNavigationButtons.h View File

2
 #import <UIKit/UIKit.h>
2
 #import <UIKit/UIKit.h>
3
 #import "RNNButtonOptions.h"
3
 #import "RNNButtonOptions.h"
4
 #import "RNNRootViewCreator.h"
4
 #import "RNNRootViewCreator.h"
5
+#import "RNNReactComponentManager.h"
5
 
6
 
6
 @interface RNNNavigationButtons : NSObject
7
 @interface RNNNavigationButtons : NSObject
7
 
8
 
8
--(instancetype)initWithViewController:(UIViewController*)viewController rootViewCreator:(id<RNNRootViewCreator>)creator;
9
+-(instancetype)initWithViewController:(UIViewController*)viewController componentManager:(RNNReactComponentManager *)componentManager;
9
 
10
 
10
 -(void)applyLeftButtons:(NSArray*)leftButtons rightButtons:(NSArray*)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle;
11
 -(void)applyLeftButtons:(NSArray*)leftButtons rightButtons:(NSArray*)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle;
11
 
12
 

+ 9
- 5
lib/ios/RNNNavigationButtons.m View File

7
 
7
 
8
 @interface RNNNavigationButtons()
8
 @interface RNNNavigationButtons()
9
 
9
 
10
-@property (weak, nonatomic) UIViewController* viewController;
10
+@property (weak, nonatomic) UIViewController<RNNLayoutProtocol>* viewController;
11
 @property (strong, nonatomic) RNNButtonOptions* defaultLeftButtonStyle;
11
 @property (strong, nonatomic) RNNButtonOptions* defaultLeftButtonStyle;
12
 @property (strong, nonatomic) RNNButtonOptions* defaultRightButtonStyle;
12
 @property (strong, nonatomic) RNNButtonOptions* defaultRightButtonStyle;
13
-@property (nonatomic) id<RNNRootViewCreator> creator;
13
+@property (strong, nonatomic) RNNReactComponentManager* componentManager;
14
 @end
14
 @end
15
 
15
 
16
 @implementation RNNNavigationButtons
16
 @implementation RNNNavigationButtons
17
 
17
 
18
--(instancetype)initWithViewController:(UIViewController*)viewController rootViewCreator:(id<RNNRootViewCreator>)creator {
18
+-(instancetype)initWithViewController:(UIViewController<RNNLayoutProtocol>*)viewController componentManager:(id)componentManager {
19
 	self = [super init];
19
 	self = [super init];
20
 	
20
 	
21
 	self.viewController = viewController;
21
 	self.viewController = viewController;
22
-	self.creator = creator;
22
+	self.componentManager = componentManager;
23
 	
23
 	
24
 	return self;
24
 	return self;
25
 }
25
 }
85
 	
85
 	
86
 	RNNUIBarButtonItem *barButtonItem;
86
 	RNNUIBarButtonItem *barButtonItem;
87
 	if (component) {
87
 	if (component) {
88
-		RCTRootView *view = (RCTRootView*)[self.creator createCustomReactView:component[@"name"] rootViewId:component[@"componentId"]];
88
+		RNNComponentOptions* componentOptions = [RNNComponentOptions new];
89
+		componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]];
90
+		componentOptions.name = [[Text alloc] initWithValue:component[@"name"]];
91
+		
92
+		RNNReactView *view = [_componentManager createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId reactViewReadyBlock:nil];
89
 		barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view];
93
 		barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view];
90
 	} else if (iconImage) {
94
 	} else if (iconImage) {
91
 		barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage];
95
 		barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage];

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

10
 @property (nonatomic, strong) RNNNavigationOptions* options;
10
 @property (nonatomic, strong) RNNNavigationOptions* options;
11
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
11
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
12
 
12
 
13
+
14
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo creator:(id<RNNRootViewCreator>)creator childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions presenter:(RNNBasePresenter *)presenter;
15
+
13
 - (void)setTopBarBackgroundColor:(UIColor *)backgroundColor;
16
 - (void)setTopBarBackgroundColor:(UIColor *)backgroundColor;
14
 
17
 
15
 @end
18
 @end

+ 26
- 1
lib/ios/RNNNavigationController.m View File

13
 
13
 
14
 @implementation RNNNavigationController
14
 @implementation RNNNavigationController
15
 
15
 
16
-- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions presenter:(RNNNavigationControllerPresenter *)presenter {
16
+- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo creator:(id<RNNRootViewCreator>)creator childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions presenter:(RNNNavigationControllerPresenter *)presenter {
17
 	self = [super init];
17
 	self = [super init];
18
 
18
 
19
 	self.presenter = presenter;
19
 	self.presenter = presenter;
37
 
37
 
38
 - (void)onChildWillAppear {
38
 - (void)onChildWillAppear {
39
 	[_presenter applyOptions:self.resolveOptions];
39
 	[_presenter applyOptions:self.resolveOptions];
40
+	[_presenter renderComponents:self.resolveOptions perform:nil];
40
 	[((UIViewController<RNNParentProtocol> *)self.parentViewController) onChildWillAppear];
41
 	[((UIViewController<RNNParentProtocol> *)self.parentViewController) onChildWillAppear];
41
 }
42
 }
42
 
43
 
53
 	[self.options overrideOptions:options];
54
 	[self.options overrideOptions:options];
54
 }
55
 }
55
 
56
 
57
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
58
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
59
+		dispatch_group_t group = dispatch_group_create();
60
+		for (UIViewController<RNNLayoutProtocol>* childViewController in self.childViewControllers) {
61
+			dispatch_group_enter(group);
62
+			dispatch_async(dispatch_get_main_queue(), ^{
63
+				[childViewController renderTreeAndWait:wait perform:^{
64
+					dispatch_group_leave(group);
65
+				}];
66
+			});
67
+		}
68
+		
69
+		dispatch_group_enter(group);
70
+		[self.presenter renderComponents:self.resolveOptions perform:^{
71
+			dispatch_group_leave(group);
72
+		}];
73
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
74
+		
75
+		dispatch_async(dispatch_get_main_queue(), ^{
76
+			readyBlock();
77
+		});
78
+	});
79
+}
80
+
56
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
81
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
57
 	return self.getCurrentChild.supportedInterfaceOrientations;
82
 	return self.getCurrentChild.supportedInterfaceOrientations;
58
 }
83
 }

+ 6
- 0
lib/ios/RNNNavigationControllerPresenter.h View File

1
 #import "RNNBasePresenter.h"
1
 #import "RNNBasePresenter.h"
2
+#import "RNNRootViewCreator.h"
3
+#import "RNNReactComponentManager.h"
2
 
4
 
3
 @interface RNNNavigationControllerPresenter : RNNBasePresenter
5
 @interface RNNNavigationControllerPresenter : RNNBasePresenter
4
 
6
 
7
+- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager;
8
+
5
 - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options;
9
 - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options;
6
 
10
 
11
+- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
12
+
7
 @end
13
 @end

+ 98
- 0
lib/ios/RNNNavigationControllerPresenter.m View File

2
 #import "UINavigationController+RNNOptions.h"
2
 #import "UINavigationController+RNNOptions.h"
3
 #import "RNNNavigationController.h"
3
 #import "RNNNavigationController.h"
4
 #import <React/RCTConvert.h>
4
 #import <React/RCTConvert.h>
5
+#import "RNNCustomTitleView.h"
5
 
6
 
7
+@interface RNNNavigationControllerPresenter() {
8
+	RNNReactComponentManager* _componentManager;
9
+	UIView* _customTopBar;
10
+	UIView* _customTopBarBackground;
11
+}
12
+
13
+@end
6
 @implementation RNNNavigationControllerPresenter
14
 @implementation RNNNavigationControllerPresenter
7
 
15
 
16
+- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager {
17
+	self = [super init];
18
+	_componentManager = componentManager;
19
+	return self;
20
+}
21
+
22
+- (void)bindViewController:(UIViewController *)bindedViewController {
23
+	self.bindedViewController = bindedViewController;
24
+}
25
+
8
 - (void)applyOptions:(RNNNavigationOptions *)options {
26
 - (void)applyOptions:(RNNNavigationOptions *)options {
9
 	[super applyOptions:options];
27
 	[super applyOptions:options];
10
 	
28
 	
112
 	
130
 	
113
 	[navigationController rnn_setNavigationBarFontFamily:[newOptions.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[newOptions.topBar.title.fontSize getWithDefaultValue:nil] color:[newOptions.topBar.title.color getWithDefaultValue:nil]];
131
 	[navigationController rnn_setNavigationBarFontFamily:[newOptions.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[newOptions.topBar.title.fontSize getWithDefaultValue:nil] color:[newOptions.topBar.title.color getWithDefaultValue:nil]];
114
 	
132
 	
133
+	if (newOptions.topBar.component.name.hasValue) {
134
+		[self setCustomNavigationBarView:newOptions perform:nil];
135
+	}
136
+	
137
+	if (newOptions.topBar.background.component.name.hasValue) {
138
+		[self setCustomNavigationComponentBackground:newOptions perform:nil];
139
+	}
140
+}
141
+
142
+- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
143
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
144
+		dispatch_group_t group = dispatch_group_create();
145
+		
146
+		dispatch_group_enter(group);
147
+		dispatch_async(dispatch_get_main_queue(), ^{
148
+			[self setCustomNavigationBarView:options perform:^{
149
+				dispatch_group_leave(group);
150
+			}];
151
+		});
152
+		
153
+		dispatch_group_enter(group);
154
+		dispatch_async(dispatch_get_main_queue(), ^{
155
+			[self setCustomNavigationComponentBackground:options perform:^{
156
+				dispatch_group_leave(group);
157
+			}];
158
+		});
159
+		
160
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
161
+		
162
+		dispatch_async(dispatch_get_main_queue(), ^{
163
+			if (readyBlock) {
164
+				readyBlock();
165
+			}
166
+		});
167
+	});
168
+}
169
+
170
+- (void)setCustomNavigationBarView:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
171
+	RNNNavigationController* navigationController = self.bindedViewController;
172
+	if (![options.topBar.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
173
+		readyBlock();
174
+		readyBlock = nil;
175
+	}
176
+	if (options.topBar.component.name.hasValue) {
177
+		RCTRootView *reactView = [_componentManager createComponentIfNotExists:options.topBar.component parentComponentId:navigationController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
178
+		
179
+		_customTopBar = [[RNNCustomTitleView alloc] initWithFrame:navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
180
+		reactView.backgroundColor = UIColor.clearColor;
181
+		_customTopBar.backgroundColor = UIColor.clearColor;
182
+		[navigationController.navigationBar addSubview:_customTopBar];
183
+	} else {
184
+		[_customTopBar removeFromSuperview];
185
+		if (readyBlock) {
186
+			readyBlock();
187
+		}
188
+	}
189
+}
190
+
191
+- (void)setCustomNavigationComponentBackground:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
192
+	RNNNavigationController* navigationController = self.bindedViewController;
193
+	if (![options.topBar.background.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
194
+		readyBlock();
195
+		readyBlock = nil;
196
+	}
197
+	if (options.topBar.background.component.name.hasValue) {
198
+		RCTRootView *reactView = [_componentManager createComponentIfNotExists:options.topBar.background.component parentComponentId:navigationController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
199
+		
200
+		_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
201
+		[navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
202
+	} else {
203
+		[_customTopBarBackground removeFromSuperview];
204
+		if (readyBlock) {
205
+			readyBlock();
206
+		}
207
+	}
208
+}
209
+
210
+- (void)dealloc {
211
+	RNNNavigationController* navigationController = self.bindedViewController;
212
+	[_componentManager removeComponent:navigationController.layoutInfo.componentId];
115
 }
213
 }
116
 
214
 
117
 @end
215
 @end

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

3
 
3
 
4
 @protocol RNNParentProtocol <RNNLayoutProtocol, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
4
 @protocol RNNParentProtocol <RNNLayoutProtocol, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>
5
 
5
 
6
-@required
7
 
6
 
7
+@optional
8
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions presenter:(RNNBasePresenter *)presenter;
8
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo childViewControllers:(NSArray *)childViewControllers options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions presenter:(RNNBasePresenter *)presenter;
9
 
9
 
10
+@required
10
 - (void)onChildWillAppear;
11
 - (void)onChildWillAppear;
11
 
12
 
12
 @end
13
 @end

+ 17
- 0
lib/ios/RNNReactComponentManager.h View File

1
+#import <Foundation/Foundation.h>
2
+#import "RNNReactView.h"
3
+#import "RNNComponentOptions.h"
4
+#import "RNNStore.h"
5
+#import "RNNRootViewCreator.h"
6
+
7
+@interface RNNReactComponentManager : NSObject
8
+
9
+- (instancetype)initWithCreator:(id<RNNRootViewCreator>)creator;
10
+
11
+- (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
12
+
13
+- (void)removeComponent:(NSString *)componentId;
14
+
15
+- (void)clean;
16
+
17
+@end

+ 52
- 0
lib/ios/RNNReactComponentManager.m View File

1
+#import "RNNReactComponentManager.h"
2
+
3
+@interface RNNReactComponentManager () {
4
+	id<RNNRootViewCreator> _creator;
5
+	NSMutableDictionary* _componentStore;
6
+}
7
+
8
+@end
9
+
10
+@implementation RNNReactComponentManager
11
+
12
+- (instancetype)initWithCreator:(id<RNNRootViewCreator>)creator {
13
+	self = [super init];
14
+	_creator = creator;
15
+	_componentStore = [NSMutableDictionary new];
16
+	return self;
17
+}
18
+
19
+- (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
20
+	NSMutableDictionary* parentComponentDict = [self componentsForParentId:parentComponentId];
21
+	
22
+	RNNReactView* reactView = [parentComponentDict objectForKey:component.componentId.get];
23
+	if (!reactView) {
24
+		reactView = (RNNReactView *)[_creator createRootViewFromComponentOptions:component reactViewReadyBlock:reactViewReadyBlock];
25
+		[parentComponentDict setObject:reactView forKey:component.componentId.get];
26
+	} else if (reactViewReadyBlock) {
27
+		reactViewReadyBlock();
28
+	}
29
+	
30
+	return reactView;
31
+}
32
+
33
+- (NSMutableDictionary *)componentsForParentId:(NSString *)parentComponentId {
34
+	if (!_componentStore[parentComponentId]) {
35
+		[_componentStore setObject:[NSMutableDictionary new] forKey:parentComponentId];;
36
+	}
37
+	
38
+	return [_componentStore objectForKey:parentComponentId];;
39
+}
40
+
41
+- (void)removeComponent:(NSString *)componentId {
42
+	if ([_componentStore objectForKey:componentId]) {
43
+		[_componentStore removeObjectForKey:componentId];
44
+	}
45
+}
46
+
47
+- (void)clean {
48
+	[_componentStore removeAllObjects];
49
+}
50
+
51
+
52
+@end

+ 0
- 6
lib/ios/RNNReactRootView.h View File

1
-#import <UIKit/UIKit.h>
2
-#import "RNNReactView.h"
3
-
4
-@interface RNNReactRootView : RNNReactView
5
-
6
-@end

+ 0
- 16
lib/ios/RNNReactRootView.m View File

1
-#import "RNNReactRootView.h"
2
-#import "RCTHelpers.h"
3
-#import <React/RCTUIManager.h>
4
-
5
-@implementation RNNReactRootView
6
-
7
-- (void)layoutSubviews {
8
-	[super layoutSubviews];
9
-	[self.bridge.uiManager setSize:self.bounds.size forView:self];
10
-}
11
-
12
-- (void)contentDidAppear:(NSNotification *)notification {
13
-	
14
-}
15
-
16
-@end

+ 10
- 18
lib/ios/RNNReactRootViewCreator.m View File

1
 
1
 
2
 #import "RNNReactRootViewCreator.h"
2
 #import "RNNReactRootViewCreator.h"
3
-#import "RNNReactRootView.h"
4
 #import "RNNReactView.h"
3
 #import "RNNReactView.h"
5
 
4
 
6
 @implementation RNNReactRootViewCreator {
5
 @implementation RNNReactRootViewCreator {
7
 	RCTBridge *_bridge;
6
 	RCTBridge *_bridge;
8
 }
7
 }
9
 
8
 
10
--(instancetype)initWithBridge:(RCTBridge*)bridge {
9
+- (instancetype)initWithBridge:(RCTBridge*)bridge {
11
 	self = [super init];
10
 	self = [super init];
12
 	
11
 	
13
 	_bridge = bridge;
12
 	_bridge = bridge;
14
 	
13
 	
15
 	return self;
14
 	return self;
16
-	
17
 }
15
 }
18
 
16
 
19
-- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId {
17
+- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
20
 	if (!rootViewId) {
18
 	if (!rootViewId) {
21
 		@throw [NSException exceptionWithName:@"MissingViewId" reason:@"Missing view id" userInfo:nil];
19
 		@throw [NSException exceptionWithName:@"MissingViewId" reason:@"Missing view id" userInfo:nil];
22
 	}
20
 	}
23
 	
21
 	
24
-	UIView *view = [[RNNReactRootView alloc] initWithBridge:_bridge
25
-										 moduleName:name
26
-								  initialProperties:@{@"componentId": rootViewId}];
22
+	RNNReactView *view = [[RNNReactView alloc] initWithBridge:_bridge
23
+														   moduleName:name
24
+													initialProperties:@{@"componentId": rootViewId}
25
+												  reactViewReadyBlock:reactViewReadyBlock];
27
 	return view;
26
 	return view;
28
 }
27
 }
29
 
28
 
30
-- (UIView*)createCustomReactView:(NSString*)name rootViewId:(NSString*)rootViewId {
31
-	if (!rootViewId) {
32
-		@throw [NSException exceptionWithName:@"MissingViewId" reason:@"Missing view id" userInfo:nil];
33
-	}
34
-	
35
-	UIView *view = [[RNNReactView alloc] initWithBridge:_bridge
36
-												 moduleName:name
37
-										  initialProperties:@{@"componentId": rootViewId}];
38
-	return view;
29
+- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions {
30
+	return [self createRootView:componentOptions.name.get rootViewId:componentOptions.componentId.get reactViewReadyBlock:nil];
39
 }
31
 }
40
 
32
 
41
--(UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions {
42
-	return [self createCustomReactView:componentOptions.name.get rootViewId:componentOptions.componentId.get];
33
+- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
34
+	return [self createRootView:componentOptions.name.get rootViewId:componentOptions.componentId.get reactViewReadyBlock:reactViewReadyBlock];
43
 }
35
 }
44
 
36
 
45
 @end
37
 @end

+ 5
- 0
lib/ios/RNNReactView.h View File

1
 #import <React/RCTRootView.h>
1
 #import <React/RCTRootView.h>
2
 #import <React/RCTRootViewDelegate.h>
2
 #import <React/RCTRootViewDelegate.h>
3
 
3
 
4
+typedef void (^RNNReactViewReadyCompletionBlock)(void);
5
+
4
 @interface RNNReactView : RCTRootView <RCTRootViewDelegate>
6
 @interface RNNReactView : RCTRootView <RCTRootViewDelegate>
5
 
7
 
8
+- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
9
+
6
 @property (nonatomic, copy) void (^rootViewDidChangeIntrinsicSize)(CGSize intrinsicSize);
10
 @property (nonatomic, copy) void (^rootViewDidChangeIntrinsicSize)(CGSize intrinsicSize);
11
+@property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
7
 
12
 
8
 - (void)setAlignment:(NSString *)alignment;
13
 - (void)setAlignment:(NSString *)alignment;
9
 
14
 

+ 13
- 5
lib/ios/RNNReactView.m View File

1
 #import "RNNReactView.h"
1
 #import "RNNReactView.h"
2
 #import "RCTHelpers.h"
2
 #import "RCTHelpers.h"
3
+#import <React/RCTUIManager.h>
3
 
4
 
4
 @implementation RNNReactView
5
 @implementation RNNReactView
5
 
6
 
6
-- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties {
7
+- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
7
 	self = [super initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
8
 	self = [super initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
8
-	
9
-#ifdef DEBUG
10
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidAppear:) name:RCTContentDidAppearNotification object:nil];
9
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidAppear:) name:RCTContentDidAppearNotification object:nil];
11
-#endif
10
+	 _reactViewReadyBlock = reactViewReadyBlock;
12
 	
11
 	
13
 	return self;
12
 	return self;
14
 }
13
 }
15
 
14
 
16
 - (void)contentDidAppear:(NSNotification *)notification {
15
 - (void)contentDidAppear:(NSNotification *)notification {
16
+#ifdef DEBUG
17
 	if ([((RNNReactView *)notification.object).moduleName isEqualToString:self.moduleName]) {
17
 	if ([((RNNReactView *)notification.object).moduleName isEqualToString:self.moduleName]) {
18
 		[RCTHelpers removeYellowBox:self];
18
 		[RCTHelpers removeYellowBox:self];
19
-		[[NSNotificationCenter defaultCenter] removeObserver:self];
20
 	}
19
 	}
20
+#endif
21
+	
22
+	RNNReactView* appearedView = notification.object;
23
+	
24
+	 if (_reactViewReadyBlock && [appearedView.appProperties[@"componentId"] isEqual:self.appProperties[@"componentId"]]) {
25
+	 	_reactViewReadyBlock();
26
+		 _reactViewReadyBlock = nil;
27
+		 [[NSNotificationCenter defaultCenter] removeObserver:self];
28
+	 }
21
 }
29
 }
22
 
30
 
23
 - (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {
31
 - (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {

+ 24
- 135
lib/ios/RNNRootViewController.m View File

1
 #import "RNNRootViewController.h"
1
 #import "RNNRootViewController.h"
2
 #import <React/RCTConvert.h>
2
 #import <React/RCTConvert.h>
3
 #import "RNNAnimator.h"
3
 #import "RNNAnimator.h"
4
-#import "RNNCustomTitleView.h"
5
 #import "RNNPushAnimation.h"
4
 #import "RNNPushAnimation.h"
6
 #import "RNNReactView.h"
5
 #import "RNNReactView.h"
7
 #import "RNNParentProtocol.h"
6
 #import "RNNParentProtocol.h"
8
-#import "RNNTitleViewHelper.h"
9
 
7
 
10
-@interface RNNRootViewController() {
11
-	RNNReactView* _customTitleView;
12
-	UIView* _customTopBar;
13
-	UIView* _customTopBarBackground;
14
-	BOOL _isBeingPresented;
15
-}
16
-
17
-@property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
18
-
19
-@end
20
 
8
 
21
 @implementation RNNRootViewController
9
 @implementation RNNRootViewController
22
 
10
 
27
 	
15
 	
28
 	self.layoutInfo = layoutInfo;
16
 	self.layoutInfo = layoutInfo;
29
 	self.creator = creator;
17
 	self.creator = creator;
30
-	if (self.creator) {
31
-		self.view = [creator createRootView:self.layoutInfo.name rootViewId:self.layoutInfo.componentId];
32
-		[[NSNotificationCenter defaultCenter] addObserver:self
33
-												 selector:@selector(reactViewReady)
34
-													 name: @"RCTContentDidAppearNotification"
35
-												   object:nil];
36
-	}
37
 	
18
 	
38
 	self.eventEmitter = eventEmitter;
19
 	self.eventEmitter = eventEmitter;
39
 	self.presenter = presenter;
20
 	self.presenter = presenter;
40
-	[self.presenter bindViewController:self viewCreator:self.creator];
21
+	[self.presenter bindViewController:self];
41
 	self.options = options;
22
 	self.options = options;
42
 	self.defaultOptions = defaultOptions;
23
 	self.defaultOptions = defaultOptions;
43
 	
24
 	
74
 - (void)mergeOptions:(RNNNavigationOptions *)options {
55
 - (void)mergeOptions:(RNNNavigationOptions *)options {
75
 	[_presenter mergeOptions:options currentOptions:self.options defaultOptions:self.defaultOptions];
56
 	[_presenter mergeOptions:options currentOptions:self.options defaultOptions:self.defaultOptions];
76
 	[((UIViewController<RNNLayoutProtocol> *)self.parentViewController) mergeOptions:options];
57
 	[((UIViewController<RNNLayoutProtocol> *)self.parentViewController) mergeOptions:options];
77
-	
78
-	[self initCustomViews];
79
 }
58
 }
80
 
59
 
81
 - (void)overrideOptions:(RNNNavigationOptions *)options {
60
 - (void)overrideOptions:(RNNNavigationOptions *)options {
84
 
63
 
85
 - (void)viewWillAppear:(BOOL)animated{
64
 - (void)viewWillAppear:(BOOL)animated{
86
 	[super viewWillAppear:animated];
65
 	[super viewWillAppear:animated];
87
-	_isBeingPresented = YES;
88
 	
66
 	
89
 	[_presenter applyOptions:self.resolveOptions];
67
 	[_presenter applyOptions:self.resolveOptions];
90
-	[((UIViewController<RNNParentProtocol> *)self.parentViewController) onChildWillAppear];
68
+	[_presenter renderComponents:self.resolveOptions perform:nil];
91
 	
69
 	
92
-	[self initCustomViews];
70
+	[((UIViewController<RNNParentProtocol> *)self.parentViewController) onChildWillAppear];
93
 }
71
 }
94
 
72
 
95
 - (RNNNavigationOptions *)resolveOptions {
73
 - (RNNNavigationOptions *)resolveOptions {
103
 
81
 
104
 - (void)viewWillDisappear:(BOOL)animated {
82
 - (void)viewWillDisappear:(BOOL)animated {
105
 	[super viewWillDisappear:animated];
83
 	[super viewWillDisappear:animated];
106
-	_isBeingPresented = NO;
107
 }
84
 }
108
 
85
 
109
 - (void)viewDidDisappear:(BOOL)animated {
86
 - (void)viewDidDisappear:(BOOL)animated {
111
 	[self.eventEmitter sendComponentDidDisappear:self.layoutInfo.componentId componentName:self.layoutInfo.name];
88
 	[self.eventEmitter sendComponentDidDisappear:self.layoutInfo.componentId componentName:self.layoutInfo.name];
112
 }
89
 }
113
 
90
 
114
-- (void)reactViewReady {
115
-	if (_reactViewReadyBlock) {
116
-		_reactViewReadyBlock();
117
-		_reactViewReadyBlock = nil;
91
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
92
+	if (self.isExternalViewController) {
93
+		if (readyBlock) {
94
+			readyBlock();
95
+		}
96
+		return;
118
 	}
97
 	}
119
 	
98
 	
120
-	[[NSNotificationCenter defaultCenter] removeObserver:self name:@"RCTContentDidAppearNotification" object:nil];
121
-}
122
-
123
-
124
-- (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
125
-	if (wait && !self.isExternalViewController) {
126
-		[self onReactViewReady:readyBlock];
127
-	} else {
128
-		readyBlock();
99
+	__block RNNReactViewReadyCompletionBlock readyBlockCopy = readyBlock;
100
+	UIView* reactView = [_creator createRootView:self.layoutInfo.name rootViewId:self.layoutInfo.componentId reactViewReadyBlock:^{
101
+		[_presenter renderComponents:self.resolveOptions perform:^{
102
+			if (readyBlockCopy) {
103
+				readyBlockCopy();
104
+				readyBlockCopy = nil;
105
+			}
106
+		}];
107
+	}];
108
+	reactView.backgroundColor = [UIColor clearColor];
109
+	self.view = reactView;
110
+	
111
+	if (!wait && readyBlock) {
112
+		readyBlockCopy();
113
+		readyBlockCopy = nil;
129
 	}
114
 	}
130
 }
115
 }
131
 
116
 
137
 	return self;
122
 	return self;
138
 }
123
 }
139
 
124
 
140
-- (void)onReactViewReady:(RNNReactViewReadyCompletionBlock)readyBlock {
141
-	if (self.isExternalViewController) {
142
-		readyBlock();
143
-	} else {
144
-		self.reactViewReadyBlock = readyBlock;
145
-	}
146
-}
147
-
148
 -(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
125
 -(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
149
 	[self.eventEmitter sendOnSearchBarUpdated:self.layoutInfo.componentId
126
 	[self.eventEmitter sendOnSearchBarUpdated:self.layoutInfo.componentId
150
 										 text:searchController.searchBar.text
127
 										 text:searchController.searchBar.text
155
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
132
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
156
 }
133
 }
157
 
134
 
158
-- (void)initCustomViews {
159
-	[self setCustomNavigationTitleView];
160
-	[self setCustomNavigationBarView];
161
-	[self setCustomNavigationComponentBackground];
162
-	
163
-	if (!_customTitleView) {
164
-		[self setTitleViewWithSubtitle];
165
-	}
166
-}
167
-
168
-- (void)setTitleViewWithSubtitle {
169
-	if (self.resolveOptions.topBar.subtitle.text.hasValue) {
170
-		RNNTitleViewHelper* titleViewHelper = [[RNNTitleViewHelper alloc] initWithTitleViewOptions:self.resolveOptions.topBar.title subTitleOptions:self.resolveOptions.topBar.subtitle viewController:self];
171
-		[titleViewHelper setup];
172
-	}
173
-}
174
-
175
-- (void)setCustomNavigationTitleView {
176
-	if (!_customTitleView && _isBeingPresented) {
177
-		if (self.resolveOptions.topBar.title.component.name.hasValue) {
178
-			_customTitleView = (RNNReactView*)[_creator createRootViewFromComponentOptions:self.resolveOptions.topBar.title.component];
179
-			_customTitleView.backgroundColor = UIColor.clearColor;
180
-			NSString* alignment = [self.resolveOptions.topBar.title.component.alignment getWithDefaultValue:@""];
181
-			[_customTitleView setAlignment:alignment];
182
-			BOOL isCenter = [alignment isEqualToString:@"center"];
183
-			__weak RNNReactView *weakTitleView = _customTitleView;
184
-			CGRect frame = self.navigationController.navigationBar.bounds;
185
-			[_customTitleView setFrame:frame];
186
-			[_customTitleView setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicContentSize) {
187
-				if (isCenter) {
188
-					[weakTitleView setFrame:CGRectMake(0, 0, intrinsicContentSize.width, intrinsicContentSize.height)];
189
-				} else {
190
-					[weakTitleView setFrame:frame];
191
-				}
192
-			}];
193
-			
194
-			self.navigationItem.titleView = _customTitleView;
195
-		}
196
-	} else if (_customTitleView && _customTitleView.superview == nil) {
197
-		if ([self.navigationItem.title isKindOfClass:[RNNCustomTitleView class]] && !_customTitleView) {
198
-			self.navigationItem.title = nil;
199
-		}
200
-		self.navigationItem.titleView = _customTitleView;
201
-	}
202
-}
203
-
204
-- (void)setCustomNavigationBarView {
205
-	if (!_customTopBar) {
206
-		if (self.resolveOptions.topBar.component.name.hasValue) {
207
-			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.resolveOptions.topBar.component];
208
-			
209
-			_customTopBar = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
210
-			reactView.backgroundColor = UIColor.clearColor;
211
-			_customTopBar.backgroundColor = UIColor.clearColor;
212
-			[self.navigationController.navigationBar addSubview:_customTopBar];
213
-		} else if ([[self.navigationController.navigationBar.subviews lastObject] isKindOfClass:[RNNCustomTitleView class]] && !_customTopBar) {
214
-			[[self.navigationController.navigationBar.subviews lastObject] removeFromSuperview];
215
-		}
216
-	} else if (_customTopBar && _customTopBar.superview == nil) {
217
-		if ([[self.navigationController.navigationBar.subviews lastObject] isKindOfClass:[RNNCustomTitleView class]] && !_customTopBar) {
218
-			[[self.navigationController.navigationBar.subviews lastObject] removeFromSuperview];
219
-		}
220
-		[self.navigationController.navigationBar addSubview:_customTopBar];
221
-	}
222
-}
223
-
224
-- (void)setCustomNavigationComponentBackground {
225
-	if (!_customTopBarBackground) {
226
-		if (self.resolveOptions.topBar.background.component.name.hasValue) {
227
-			RCTRootView *reactView = (RCTRootView*)[_creator createRootViewFromComponentOptions:self.resolveOptions.topBar.background.component];
228
-			
229
-			_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
230
-			[self.navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
231
-		} else if (self.navigationController.navigationBar.subviews.count > 1 && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
232
-			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
233
-		}
234
-	} if (_customTopBarBackground && _customTopBarBackground.superview == nil) {
235
-		if (self.navigationController.navigationBar.subviews.count && [[self.navigationController.navigationBar.subviews objectAtIndex:1] isKindOfClass:[RNNCustomTitleView class]]) {
236
-			[[self.navigationController.navigationBar.subviews objectAtIndex:1] removeFromSuperview];
237
-		}
238
-		[self.navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
239
-		self.navigationController.navigationBar.clipsToBounds = YES;
240
-	}
241
-}
242
-
243
 -(BOOL)isCustomTransitioned {
135
 -(BOOL)isCustomTransitioned {
244
 	return self.resolveOptions.customTransition.animations != nil;
136
 	return self.resolveOptions.customTransition.animations != nil;
245
 }
137
 }
376
 	self.navigationItem.titleView = nil;
268
 	self.navigationItem.titleView = nil;
377
 	self.navigationItem.rightBarButtonItems = nil;
269
 	self.navigationItem.rightBarButtonItems = nil;
378
 	self.navigationItem.leftBarButtonItems = nil;
270
 	self.navigationItem.leftBarButtonItems = nil;
379
-	_customTopBar = nil;
380
-	_customTitleView = nil;
381
-	_customTopBarBackground = nil;
382
 }
271
 }
383
 
272
 
384
 @end
273
 @end

+ 3
- 2
lib/ios/RNNRootViewCreator.h View File

1
 
1
 
2
 #import <UIKit/UIKit.h>
2
 #import <UIKit/UIKit.h>
3
 #import "RNNComponentOptions.h"
3
 #import "RNNComponentOptions.h"
4
+#import "RNNReactView.h"
4
 
5
 
5
 @protocol RNNRootViewCreator
6
 @protocol RNNRootViewCreator
6
 
7
 
7
-- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId;
8
+- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
8
 
9
 
9
 - (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions;
10
 - (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions;
10
 
11
 
11
-- (UIView*)createCustomReactView:(NSString*)name rootViewId:(NSString*)rootViewId;
12
+- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
12
 
13
 
13
 @end
14
 @end
14
 
15
 

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

7
 @property (nonatomic, strong) RNNTransitionStateHolder* content;
7
 @property (nonatomic, strong) RNNTransitionStateHolder* content;
8
 @property (nonatomic, strong) RNNTransitionStateHolder* bottomTabs;
8
 @property (nonatomic, strong) RNNTransitionStateHolder* bottomTabs;
9
 
9
 
10
-@property (nonatomic) BOOL enable;
11
-@property (nonatomic) BOOL waitForRender;
10
+@property (nonatomic, strong) Bool* enable;
11
+@property (nonatomic, strong) Bool* waitForRender;
12
 
12
 
13
 - (BOOL)hasCustomAnimation;
13
 - (BOOL)hasCustomAnimation;
14
 
14
 

+ 2
- 3
lib/ios/RNNScreenTransition.m View File

8
 	self.topBar = dict[@"topBar"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"topBar"]] : nil;
8
 	self.topBar = dict[@"topBar"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"topBar"]] : nil;
9
 	self.content = dict[@"content"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"content"]] : nil;
9
 	self.content = dict[@"content"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"content"]] : nil;
10
 	self.bottomTabs = dict[@"bottomTabs"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"bottomTabs"]] : nil;
10
 	self.bottomTabs = dict[@"bottomTabs"] ? [[RNNTransitionStateHolder alloc] initWithDict:dict[@"bottomTabs"]] : nil;
11
-
12
-	self.enable = dict[@"enabled"] ? [dict[@"enabled"] boolValue] : YES;
13
-	self.waitForRender = dict[@"waitForRender"] ? [dict[@"waitForRender"] boolValue] : NO;
11
+	self.enable = [BoolParser parse:dict key:@"enabled"];
12
+	self.waitForRender = [BoolParser parse:dict key:@"waitForRender"];
14
 
13
 
15
 	return self;
14
 	return self;
16
 }
15
 }

+ 1
- 0
lib/ios/RNNSideMenuChildVC.h View File

1
 #import <UIKit/UIKit.h>
1
 #import <UIKit/UIKit.h>
2
 #import "RNNParentProtocol.h"
2
 #import "RNNParentProtocol.h"
3
+#import "RNNViewControllerPresenter.h"
3
 
4
 
4
 typedef NS_ENUM(NSInteger, RNNSideMenuChildType) {
5
 typedef NS_ENUM(NSInteger, RNNSideMenuChildType) {
5
 	RNNSideMenuChildTypeCenter,
6
 	RNNSideMenuChildTypeCenter,

+ 4
- 0
lib/ios/RNNSideMenuChildVC.m View File

52
 	[self.options overrideOptions:options];
52
 	[self.options overrideOptions:options];
53
 }
53
 }
54
 
54
 
55
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
56
+	[self.getCurrentChild renderTreeAndWait:wait perform:readyBlock];
57
+}
58
+
55
 - (void)bindChildViewController:(UIViewController<RNNLayoutProtocol>*)child {
59
 - (void)bindChildViewController:(UIViewController<RNNLayoutProtocol>*)child {
56
 	self.child = child;
60
 	self.child = child;
57
 	[self addChildViewController:self.child];
61
 	[self addChildViewController:self.child];

+ 1
- 0
lib/ios/RNNSideMenuController.h View File

2
 #import "RNNSideMenuChildVC.h"
2
 #import "RNNSideMenuChildVC.h"
3
 #import "MMDrawerController.h"
3
 #import "MMDrawerController.h"
4
 #import "RNNParentProtocol.h"
4
 #import "RNNParentProtocol.h"
5
+#import "RNNViewControllerPresenter.h"
5
 
6
 
6
 @interface RNNSideMenuController : MMDrawerController <RNNParentProtocol>
7
 @interface RNNSideMenuController : MMDrawerController <RNNParentProtocol>
7
 
8
 

+ 22
- 0
lib/ios/RNNSideMenuController.m View File

60
 	[self.options overrideOptions:options];
60
 	[self.options overrideOptions:options];
61
 }
61
 }
62
 
62
 
63
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
64
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
65
+		dispatch_group_t group = dispatch_group_create();
66
+		for (UIViewController<RNNLayoutProtocol>* childViewController in self.childViewControllers) {
67
+			dispatch_group_enter(group);
68
+			dispatch_async(dispatch_get_main_queue(), ^{
69
+				[childViewController renderTreeAndWait:wait perform:^{
70
+					dispatch_group_leave(group);
71
+				}];
72
+			});
73
+		}
74
+		
75
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
76
+		
77
+		dispatch_async(dispatch_get_main_queue(), ^{
78
+			readyBlock();
79
+		});
80
+	});
81
+}
82
+
63
 - (void)setAnimationType:(NSString *)animationType {
83
 - (void)setAnimationType:(NSString *)animationType {
64
 	MMDrawerControllerDrawerVisualStateBlock animationTypeStateBlock = nil;
84
 	MMDrawerControllerDrawerVisualStateBlock animationTypeStateBlock = nil;
65
 	if ([animationType isEqualToString:@"door"]) animationTypeStateBlock = [MMDrawerVisualState swingingDoorVisualStateBlock];
85
 	if ([animationType isEqualToString:@"door"]) animationTypeStateBlock = [MMDrawerVisualState swingingDoorVisualStateBlock];
129
 			else if(child.type == RNNSideMenuChildTypeRight) {
149
 			else if(child.type == RNNSideMenuChildTypeRight) {
130
 				self.right = child;
150
 				self.right = child;
131
 			}
151
 			}
152
+			
153
+			[self addChildViewController:child];
132
 		}
154
 		}
133
 		
155
 		
134
 		else {
156
 		else {

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

45
 	[self.options overrideOptions:options];
45
 	[self.options overrideOptions:options];
46
 }
46
 }
47
 
47
 
48
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
49
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
50
+		dispatch_group_t group = dispatch_group_create();
51
+		for (UIViewController<RNNLayoutProtocol>* childViewController in self.childViewControllers) {
52
+			dispatch_group_enter(group);
53
+			dispatch_async(dispatch_get_main_queue(), ^{
54
+				[childViewController renderTreeAndWait:wait perform:^{
55
+					dispatch_group_leave(group);
56
+				}];
57
+			});
58
+		}
59
+		
60
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
61
+		
62
+		dispatch_async(dispatch_get_main_queue(), ^{
63
+			readyBlock();
64
+		});
65
+	});
66
+}
67
+
48
 - (void)bindChildViewControllers:(NSArray<UIViewController<RNNLayoutProtocol> *> *)viewControllers {
68
 - (void)bindChildViewControllers:(NSArray<UIViewController<RNNLayoutProtocol> *> *)viewControllers {
49
 	[self setViewControllers:viewControllers];
69
 	[self setViewControllers:viewControllers];
50
 	UIViewController<UISplitViewControllerDelegate>* masterViewController = viewControllers[0];
70
 	UIViewController<UISplitViewControllerDelegate>* masterViewController = viewControllers[0];

+ 20
- 0
lib/ios/RNNTabBarController.m View File

60
 	[self.options overrideOptions:options];
60
 	[self.options overrideOptions:options];
61
 }
61
 }
62
 
62
 
63
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
64
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
65
+		dispatch_group_t group = dispatch_group_create();
66
+		for (UIViewController<RNNLayoutProtocol>* childViewController in self.childViewControllers) {
67
+			dispatch_group_enter(group);
68
+			dispatch_async(dispatch_get_main_queue(), ^{
69
+				[childViewController renderTreeAndWait:wait perform:^{
70
+					dispatch_group_leave(group);
71
+				}];
72
+			});
73
+		}
74
+		
75
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
76
+		
77
+		dispatch_async(dispatch_get_main_queue(), ^{
78
+			readyBlock();
79
+		});
80
+	});
81
+}
82
+
63
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
83
 - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
64
 	return self.selectedViewController.supportedInterfaceOrientations;
84
 	return self.selectedViewController.supportedInterfaceOrientations;
65
 }
85
 }

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

12
 
12
 
13
 @interface RNNTitleViewHelper : NSObject
13
 @interface RNNTitleViewHelper : NSObject
14
 
14
 
15
+@property (nonatomic, strong) RNNTitleOptions *titleOptions;
16
+@property (nonatomic, strong) RNNSubtitleOptions *subtitleOptions;
15
 
17
 
16
 - (instancetype)initWithTitleViewOptions:(RNNOptions*)titleOptions
18
 - (instancetype)initWithTitleViewOptions:(RNNOptions*)titleOptions
17
 						 subTitleOptions:(RNNOptions*)subtitleOptions
19
 						 subTitleOptions:(RNNOptions*)subtitleOptions

+ 8
- 7
lib/ios/RNNTitleViewHelper.m View File

13
 
13
 
14
 @property (nonatomic, weak) UIViewController *viewController;
14
 @property (nonatomic, weak) UIViewController *viewController;
15
 
15
 
16
-@property (nonatomic, strong) NSString *title;
17
-@property (nonatomic, strong) NSString *subtitle;
18
-
19
 @property (nonatomic, strong) RNNTitleView *titleView;
16
 @property (nonatomic, strong) RNNTitleView *titleView;
20
-@property (nonatomic, strong) RNNTitleOptions *titleOptions;
21
-@property (nonatomic, strong) RNNSubtitleOptions *subtitleOptions;
22
 
17
 
23
 @end
18
 @end
24
 
19
 
31
 	self = [super init];
26
 	self = [super init];
32
 	if (self) {
27
 	if (self) {
33
 		self.viewController = viewController;
28
 		self.viewController = viewController;
34
-		self.title = [titleOptions.text getWithDefaultValue:nil];
35
-		self.subtitle = [subtitleOptions.text getWithDefaultValue:nil];
36
 		self.titleOptions = titleOptions;
29
 		self.titleOptions = titleOptions;
37
 		self.subtitleOptions = subtitleOptions;
30
 		self.subtitleOptions = subtitleOptions;
38
 		
31
 		
40
 	return self;
33
 	return self;
41
 }
34
 }
42
 
35
 
36
+- (NSString *)title {
37
+	return [self.titleOptions.text getWithDefaultValue:nil];
38
+}
39
+
40
+- (NSString *)subtitle {
41
+	return [self.subtitleOptions.text getWithDefaultValue:nil];
42
+}
43
+
43
 +(NSString*)validateString:(NSString*)string {
44
 +(NSString*)validateString:(NSString*)string {
44
 	if ([string isEqual:[NSNull null]]) {
45
 	if ([string isEqual:[NSNull null]]) {
45
 		return nil;
46
 		return nil;

+ 0
- 1
lib/ios/RNNTopTabOptions.m View File

1
 #import "RNNTopTabOptions.h"
1
 #import "RNNTopTabOptions.h"
2
-#import "RNNRootViewController.h"
3
 
2
 
4
 @implementation RNNTopTabOptions
3
 @implementation RNNTopTabOptions
5
 
4
 

+ 1
- 1
lib/ios/RNNTopTabsViewController.h View File

6
 @property (nonatomic, retain) UIView* contentView;
6
 @property (nonatomic, retain) UIView* contentView;
7
 
7
 
8
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
8
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
9
-@property (nonatomic, retain) RNNViewControllerPresenter* presenter;
9
+@property (nonatomic, retain) RNNBasePresenter* presenter;
10
 @property (nonatomic, strong) RNNNavigationOptions* options;
10
 @property (nonatomic, strong) RNNNavigationOptions* options;
11
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
11
 @property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
12
 
12
 

+ 21
- 0
lib/ios/RNNTopTabsViewController.m View File

58
 	[self.options overrideOptions:options];
58
 	[self.options overrideOptions:options];
59
 }
59
 }
60
 
60
 
61
+- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock {
62
+	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
63
+		dispatch_group_t group = dispatch_group_create();
64
+		for (UIViewController<RNNLayoutProtocol>* childViewController in self.childViewControllers) {
65
+			dispatch_group_enter(group);
66
+			dispatch_async(dispatch_get_main_queue(), ^{
67
+				[childViewController renderTreeAndWait:wait perform:^{
68
+					dispatch_group_leave(group);
69
+				}];
70
+			});
71
+		}
72
+		
73
+		dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
74
+		
75
+		dispatch_async(dispatch_get_main_queue(), ^{
76
+			readyBlock();
77
+		});
78
+	});
79
+}
80
+
61
 - (void)createTabBar {
81
 - (void)createTabBar {
62
 	_segmentedControl = [[RNNSegmentedControl alloc] initWithSectionTitles:@[@"", @"", @""]];
82
 	_segmentedControl = [[RNNSegmentedControl alloc] initWithSectionTitles:@[@"", @"", @""]];
63
 	_segmentedControl.frame = CGRectMake(0, 0, self.view.bounds.size.width, 50);
83
 	_segmentedControl.frame = CGRectMake(0, 0, self.view.bounds.size.width, 50);
91
 	for (RNNRootViewController* childVc in viewControllers) {
111
 	for (RNNRootViewController* childVc in viewControllers) {
92
 		[childVc.view setFrame:_contentView.bounds];
112
 		[childVc.view setFrame:_contentView.bounds];
93
 //		[childVc.options.topTab applyOn:childVc];
113
 //		[childVc.options.topTab applyOn:childVc];
114
+		[self addChildViewController:childVc];
94
 	}
115
 	}
95
 	
116
 	
96
 	[self setSelectedViewControllerIndex:0];
117
 	[self setSelectedViewControllerIndex:0];

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

7
 @property (nonatomic, strong) RNNScreenTransition* push;
7
 @property (nonatomic, strong) RNNScreenTransition* push;
8
 @property (nonatomic, strong) RNNScreenTransition* pop;
8
 @property (nonatomic, strong) RNNScreenTransition* pop;
9
 @property (nonatomic, strong) RNNScreenTransition* showModal;
9
 @property (nonatomic, strong) RNNScreenTransition* showModal;
10
+@property (nonatomic, strong) RNNScreenTransition* showOverlay;
10
 @property (nonatomic, strong) RNNScreenTransition* dismissModal;
11
 @property (nonatomic, strong) RNNScreenTransition* dismissModal;
11
 @property (nonatomic, strong) RNNScreenTransition* setStackRoot;
12
 @property (nonatomic, strong) RNNScreenTransition* setStackRoot;
13
+@property (nonatomic, strong) RNNScreenTransition* setRoot;
12
 
14
 
13
 @end
15
 @end

+ 2
- 0
lib/ios/RNNTransitionsOptions.m View File

8
 	self.push = [[RNNScreenTransition alloc] initWithDict:dict[@"push"]];
8
 	self.push = [[RNNScreenTransition alloc] initWithDict:dict[@"push"]];
9
 	self.pop = [[RNNScreenTransition alloc] initWithDict:dict[@"pop"]];
9
 	self.pop = [[RNNScreenTransition alloc] initWithDict:dict[@"pop"]];
10
 	self.showModal = [[RNNScreenTransition alloc] initWithDict:dict[@"showModal"]];
10
 	self.showModal = [[RNNScreenTransition alloc] initWithDict:dict[@"showModal"]];
11
+	self.showOverlay = [[RNNScreenTransition alloc] initWithDict:dict[@"showOverlay"]];
11
 	self.dismissModal = [[RNNScreenTransition alloc] initWithDict:dict[@"dismissModal"]];
12
 	self.dismissModal = [[RNNScreenTransition alloc] initWithDict:dict[@"dismissModal"]];
12
 	self.setStackRoot = [[RNNScreenTransition alloc] initWithDict:dict[@"setStackRoot"]];
13
 	self.setStackRoot = [[RNNScreenTransition alloc] initWithDict:dict[@"setStackRoot"]];
14
+	self.setRoot = [[RNNScreenTransition alloc] initWithDict:dict[@"setRoot"]];
13
 
15
 
14
 	return self;
16
 	return self;
15
 }
17
 }

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

1
 #import "RNNBasePresenter.h"
1
 #import "RNNBasePresenter.h"
2
 #import "RNNNavigationButtons.h"
2
 #import "RNNNavigationButtons.h"
3
+#import "RNNReactComponentManager.h"
3
 
4
 
4
 @interface RNNViewControllerPresenter : RNNBasePresenter
5
 @interface RNNViewControllerPresenter : RNNBasePresenter
5
 
6
 
6
-@property (nonatomic, strong) RNNNavigationButtons* navigationButtons;
7
+- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager;
8
+
9
+- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
7
 
10
 
8
-- (void)bindViewController:(UIViewController *)bindedViewController viewCreator:(id<RNNRootViewCreator>)creator;
11
+@property (nonatomic, strong) RNNNavigationButtons* navigationButtons;
9
 
12
 
10
 @end
13
 @end

+ 94
- 3
lib/ios/RNNViewControllerPresenter.m View File

3
 #import "UITabBarController+RNNOptions.h"
3
 #import "UITabBarController+RNNOptions.h"
4
 #import "RCTConvert+Modal.h"
4
 #import "RCTConvert+Modal.h"
5
 #import "RNNReactView.h"
5
 #import "RNNReactView.h"
6
+#import "RNNCustomTitleView.h"
7
+#import "RNNTitleViewHelper.h"
8
+
9
+@interface RNNViewControllerPresenter() {
10
+	RNNReactView* _customTitleView;
11
+	RNNTitleViewHelper* _titleViewHelper;
12
+	RNNReactComponentManager* _componentManager;
13
+}
14
+
15
+@end
6
 
16
 
7
 @implementation RNNViewControllerPresenter
17
 @implementation RNNViewControllerPresenter
8
 
18
 
9
-- (void)bindViewController:(UIViewController *)bindedViewController viewCreator:(id<RNNRootViewCreator>)creator {
19
+- (instancetype)init {
20
+	self = [super init];
21
+	[[NSNotificationCenter defaultCenter] addObserver:self
22
+											 selector:@selector(cleanReactLeftovers)
23
+												 name:RCTJavaScriptWillStartLoadingNotification
24
+											   object:nil];
25
+	
26
+	return self;
27
+}
28
+
29
+- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager {
30
+	self = [self init];
31
+	_componentManager = componentManager;
32
+	return self;
33
+}
34
+
35
+- (void)bindViewController:(UIViewController *)bindedViewController {
10
 	self.bindedViewController = bindedViewController;
36
 	self.bindedViewController = bindedViewController;
11
-	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.bindedViewController rootViewCreator:creator];
37
+	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.bindedViewController componentManager:_componentManager];
12
 }
38
 }
13
 
39
 
14
 - (void)applyOptions:(RNNNavigationOptions *)options {
40
 - (void)applyOptions:(RNNNavigationOptions *)options {
23
 	[viewController rnn_setStatusBarStyle:[options.statusBar.style getWithDefaultValue:@"default"] animated:[options.statusBar.animate getWithDefaultValue:YES]];
49
 	[viewController rnn_setStatusBarStyle:[options.statusBar.style getWithDefaultValue:@"default"] animated:[options.statusBar.animate getWithDefaultValue:YES]];
24
 	[viewController rnn_setBackButtonVisible:[options.topBar.backButton.visible getWithDefaultValue:YES]];
50
 	[viewController rnn_setBackButtonVisible:[options.topBar.backButton.visible getWithDefaultValue:YES]];
25
 	[viewController rnn_setInterceptTouchOutside:[options.overlay.interceptTouchOutside getWithDefaultValue:YES]];
51
 	[viewController rnn_setInterceptTouchOutside:[options.overlay.interceptTouchOutside getWithDefaultValue:YES]];
26
-
52
+	
27
 	if (options.layout.backgroundColor.hasValue) {
53
 	if (options.layout.backgroundColor.hasValue) {
28
 		[viewController rnn_setBackgroundColor:options.layout.backgroundColor.get];
54
 		[viewController rnn_setBackgroundColor:options.layout.backgroundColor.get];
29
 	}
55
 	}
35
 		}
61
 		}
36
 		[viewController rnn_setSearchBarWithPlaceholder:[options.topBar.searchBarPlaceholder getWithDefaultValue:@""] hideNavBarOnFocusSearchBar: hideNavBarOnFocusSearchBar];
62
 		[viewController rnn_setSearchBarWithPlaceholder:[options.topBar.searchBarPlaceholder getWithDefaultValue:@""] hideNavBarOnFocusSearchBar: hideNavBarOnFocusSearchBar];
37
 	}
63
 	}
64
+	
65
+	[self setTitleViewWithSubtitle:options];
38
 }
66
 }
39
 
67
 
40
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
68
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
125
 		RCTRootView* rootView = (RCTRootView*)viewController.view;
153
 		RCTRootView* rootView = (RCTRootView*)viewController.view;
126
 		rootView.passThroughTouches = !newOptions.overlay.interceptTouchOutside.get;
154
 		rootView.passThroughTouches = !newOptions.overlay.interceptTouchOutside.get;
127
 	}
155
 	}
156
+	
157
+	[self setTitleViewWithSubtitle:newOptions];
158
+	
159
+	if (newOptions.topBar.title.component.name.hasValue) {
160
+		[self setCustomNavigationTitleView:newOptions perform:nil];
161
+	}
162
+}
163
+
164
+- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
165
+	[self setCustomNavigationTitleView:options perform:readyBlock];
166
+}
167
+
168
+- (void)setCustomNavigationTitleView:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
169
+	UIViewController<RNNLayoutProtocol>* viewController = self.bindedViewController;
170
+	if (![options.topBar.title.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
171
+		readyBlock();
172
+		readyBlock = nil;
173
+	}
174
+	
175
+	if (options.topBar.title.component.name.hasValue) {
176
+		_customTitleView = (RNNReactView*)[_componentManager createComponentIfNotExists:options.topBar.title.component parentComponentId:viewController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
177
+		_customTitleView.backgroundColor = UIColor.clearColor;
178
+		NSString* alignment = [options.topBar.title.component.alignment getWithDefaultValue:@""];
179
+		[_customTitleView setAlignment:alignment];
180
+		BOOL isCenter = [alignment isEqualToString:@"center"];
181
+		__weak RNNReactView *weakTitleView = _customTitleView;
182
+		CGRect frame = viewController.navigationController.navigationBar.bounds;
183
+		[_customTitleView setFrame:frame];
184
+		[_customTitleView setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicContentSize) {
185
+			if (isCenter) {
186
+				[weakTitleView setFrame:CGRectMake(0, 0, intrinsicContentSize.width, intrinsicContentSize.height)];
187
+			} else {
188
+				[weakTitleView setFrame:frame];
189
+			}
190
+		}];
191
+		
192
+		viewController.navigationItem.titleView = _customTitleView;
193
+	} else {
194
+		[_customTitleView removeFromSuperview];
195
+		if (readyBlock) {
196
+			readyBlock();
197
+		}
198
+	}
199
+}
200
+
201
+- (void)setTitleViewWithSubtitle:(RNNNavigationOptions *)options {
202
+	if (!_customTitleView && options.topBar.subtitle.text.hasValue) {
203
+		_titleViewHelper = [[RNNTitleViewHelper alloc] initWithTitleViewOptions:options.topBar.title subTitleOptions:options.topBar.subtitle viewController:self.bindedViewController];
204
+		[_titleViewHelper setup];
205
+	} else if (_titleViewHelper) {
206
+		if (options.topBar.title.text.hasValue) {
207
+			[_titleViewHelper setTitleOptions:options.topBar.title];
208
+		}
209
+		if (options.topBar.subtitle.text.hasValue) {
210
+			[_titleViewHelper setSubtitleOptions:options.topBar.subtitle];
211
+		}
212
+		
213
+		[_titleViewHelper setup];
214
+	}
215
+}
216
+
217
+- (void)cleanReactLeftovers {
218
+	_customTitleView = nil;
128
 }
219
 }
129
 
220
 
130
 @end
221
 @end

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

93
 		501E0217213E7EA3003365C5 /* RNNReactView.h in Headers */ = {isa = PBXBuildFile; fileRef = 501E0215213E7EA3003365C5 /* RNNReactView.h */; };
93
 		501E0217213E7EA3003365C5 /* RNNReactView.h in Headers */ = {isa = PBXBuildFile; fileRef = 501E0215213E7EA3003365C5 /* RNNReactView.h */; };
94
 		501E0218213E7EA3003365C5 /* RNNReactView.m in Sources */ = {isa = PBXBuildFile; fileRef = 501E0216213E7EA3003365C5 /* RNNReactView.m */; };
94
 		501E0218213E7EA3003365C5 /* RNNReactView.m in Sources */ = {isa = PBXBuildFile; fileRef = 501E0216213E7EA3003365C5 /* RNNReactView.m */; };
95
 		50206A6D21AFE75400B7BB1A /* RNNSideMenuParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50206A6C21AFE75400B7BB1A /* RNNSideMenuParserTest.m */; };
95
 		50206A6D21AFE75400B7BB1A /* RNNSideMenuParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50206A6C21AFE75400B7BB1A /* RNNSideMenuParserTest.m */; };
96
-		50220F48212ABDFD004C2B0A /* RNNReactRootView.h in Headers */ = {isa = PBXBuildFile; fileRef = 50220F46212ABDFD004C2B0A /* RNNReactRootView.h */; };
97
-		50220F49212ABDFD004C2B0A /* RNNReactRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 50220F47212ABDFD004C2B0A /* RNNReactRootView.m */; };
98
 		502CB46E20CD1DDA0019B2FE /* RNNBackButtonOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */; };
96
 		502CB46E20CD1DDA0019B2FE /* RNNBackButtonOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */; };
99
 		502CB46F20CD1DDA0019B2FE /* RNNBackButtonOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */; };
97
 		502CB46F20CD1DDA0019B2FE /* RNNBackButtonOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */; };
100
 		502F0E142178CF8200367CC3 /* UIViewController+RNNOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 502F0E132178CF8200367CC3 /* UIViewController+RNNOptionsTest.m */; };
98
 		502F0E142178CF8200367CC3 /* UIViewController+RNNOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 502F0E132178CF8200367CC3 /* UIViewController+RNNOptionsTest.m */; };
168
 		504AFE751FFFF0540076E904 /* RNNTopTabsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */; };
166
 		504AFE751FFFF0540076E904 /* RNNTopTabsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */; };
169
 		504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */; };
167
 		504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */; };
170
 		504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */; };
168
 		504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */; };
169
+		5050465421F8F4490035497A /* RNNReactComponentManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5050465221F8F4490035497A /* RNNReactComponentManager.h */; };
170
+		5050465521F8F4490035497A /* RNNReactComponentManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5050465321F8F4490035497A /* RNNReactComponentManager.m */; };
171
 		5053CE7F2175FB1900D0386B /* RNNDefaultOptionsHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5053CE7D2175FB1900D0386B /* RNNDefaultOptionsHelper.h */; };
171
 		5053CE7F2175FB1900D0386B /* RNNDefaultOptionsHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5053CE7D2175FB1900D0386B /* RNNDefaultOptionsHelper.h */; };
172
 		5053CE802175FB1900D0386B /* RNNDefaultOptionsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 5053CE7E2175FB1900D0386B /* RNNDefaultOptionsHelper.m */; };
172
 		5053CE802175FB1900D0386B /* RNNDefaultOptionsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 5053CE7E2175FB1900D0386B /* RNNDefaultOptionsHelper.m */; };
173
 		50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50570B242061473D006A1B5C /* RNNTitleOptions.h */; };
173
 		50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50570B242061473D006A1B5C /* RNNTitleOptions.h */; };
421
 		501E0215213E7EA3003365C5 /* RNNReactView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactView.h; sourceTree = "<group>"; };
421
 		501E0215213E7EA3003365C5 /* RNNReactView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactView.h; sourceTree = "<group>"; };
422
 		501E0216213E7EA3003365C5 /* RNNReactView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactView.m; sourceTree = "<group>"; };
422
 		501E0216213E7EA3003365C5 /* RNNReactView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactView.m; sourceTree = "<group>"; };
423
 		50206A6C21AFE75400B7BB1A /* RNNSideMenuParserTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSideMenuParserTest.m; sourceTree = "<group>"; };
423
 		50206A6C21AFE75400B7BB1A /* RNNSideMenuParserTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSideMenuParserTest.m; sourceTree = "<group>"; };
424
-		50220F46212ABDFD004C2B0A /* RNNReactRootView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactRootView.h; sourceTree = "<group>"; };
425
-		50220F47212ABDFD004C2B0A /* RNNReactRootView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactRootView.m; sourceTree = "<group>"; };
426
 		502CB43920CBCA140019B2FE /* RNNBridgeManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBridgeManagerDelegate.h; sourceTree = "<group>"; };
424
 		502CB43920CBCA140019B2FE /* RNNBridgeManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBridgeManagerDelegate.h; sourceTree = "<group>"; };
427
 		502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBackButtonOptions.h; sourceTree = "<group>"; };
425
 		502CB46C20CD1DDA0019B2FE /* RNNBackButtonOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNBackButtonOptions.h; sourceTree = "<group>"; };
428
 		502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBackButtonOptions.m; sourceTree = "<group>"; };
426
 		502CB46D20CD1DDA0019B2FE /* RNNBackButtonOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNBackButtonOptions.m; sourceTree = "<group>"; };
496
 		504AFE631FFE53070076E904 /* RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOptions.m; sourceTree = "<group>"; };
494
 		504AFE631FFE53070076E904 /* RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOptions.m; sourceTree = "<group>"; };
497
 		504AFE721FFFF0540076E904 /* RNNTopTabsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsOptions.h; sourceTree = "<group>"; };
495
 		504AFE721FFFF0540076E904 /* RNNTopTabsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsOptions.h; sourceTree = "<group>"; };
498
 		504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsOptions.m; sourceTree = "<group>"; };
496
 		504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsOptions.m; sourceTree = "<group>"; };
497
+		5050465221F8F4490035497A /* RNNReactComponentManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactComponentManager.h; sourceTree = "<group>"; };
498
+		5050465321F8F4490035497A /* RNNReactComponentManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactComponentManager.m; sourceTree = "<group>"; };
499
 		5053CE7D2175FB1900D0386B /* RNNDefaultOptionsHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNDefaultOptionsHelper.h; sourceTree = "<group>"; };
499
 		5053CE7D2175FB1900D0386B /* RNNDefaultOptionsHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNDefaultOptionsHelper.h; sourceTree = "<group>"; };
500
 		5053CE7E2175FB1900D0386B /* RNNDefaultOptionsHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNDefaultOptionsHelper.m; sourceTree = "<group>"; };
500
 		5053CE7E2175FB1900D0386B /* RNNDefaultOptionsHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNDefaultOptionsHelper.m; sourceTree = "<group>"; };
501
 		50570B242061473D006A1B5C /* RNNTitleOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTitleOptions.h; sourceTree = "<group>"; };
501
 		50570B242061473D006A1B5C /* RNNTitleOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTitleOptions.h; sourceTree = "<group>"; };
972
 				261F0E691E6F028A00989DE2 /* RNNNavigationStackManager.m */,
972
 				261F0E691E6F028A00989DE2 /* RNNNavigationStackManager.m */,
973
 				50D031322005149000386B3D /* RNNOverlayManager.h */,
973
 				50D031322005149000386B3D /* RNNOverlayManager.h */,
974
 				50D031332005149000386B3D /* RNNOverlayManager.m */,
974
 				50D031332005149000386B3D /* RNNOverlayManager.m */,
975
+				5050465221F8F4490035497A /* RNNReactComponentManager.h */,
976
+				5050465321F8F4490035497A /* RNNReactComponentManager.m */,
975
 			);
977
 			);
976
 			name = Managers;
978
 			name = Managers;
977
 			sourceTree = "<group>";
979
 			sourceTree = "<group>";
990
 				50570BE82063E09B006A1B5C /* RNNTitleViewHelper.h */,
992
 				50570BE82063E09B006A1B5C /* RNNTitleViewHelper.h */,
991
 				501CD31D214A5B6900A6E225 /* RNNLayoutInfo.h */,
993
 				501CD31D214A5B6900A6E225 /* RNNLayoutInfo.h */,
992
 				501CD31E214A5B6900A6E225 /* RNNLayoutInfo.m */,
994
 				501CD31E214A5B6900A6E225 /* RNNLayoutInfo.m */,
993
-				50220F46212ABDFD004C2B0A /* RNNReactRootView.h */,
994
-				50220F47212ABDFD004C2B0A /* RNNReactRootView.m */,
995
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
995
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
996
 				501E0216213E7EA3003365C5 /* RNNReactView.m */,
996
 				501E0216213E7EA3003365C5 /* RNNReactView.m */,
997
 				50570BE92063E09B006A1B5C /* RNNTitleViewHelper.m */,
997
 				50570BE92063E09B006A1B5C /* RNNTitleViewHelper.m */,
1279
 				5012242221736883000F5F98 /* NullColor.h in Headers */,
1279
 				5012242221736883000F5F98 /* NullColor.h in Headers */,
1280
 				50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */,
1280
 				50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */,
1281
 				50395593217485B000B0A663 /* Double.h in Headers */,
1281
 				50395593217485B000B0A663 /* Double.h in Headers */,
1282
+				5050465421F8F4490035497A /* RNNReactComponentManager.h in Headers */,
1282
 				504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
1283
 				504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
1283
 				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
1284
 				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
1284
 				5049594A216F5FE6006D2B81 /* NullText.h in Headers */,
1285
 				5049594A216F5FE6006D2B81 /* NullText.h in Headers */,
1286
 				5038A3CA216E328A009280BC /* Param.h in Headers */,
1287
 				5038A3CA216E328A009280BC /* Param.h in Headers */,
1287
 				50887CAA20F26BFE00D06111 /* RNNOverlayWindow.h in Headers */,
1288
 				50887CAA20F26BFE00D06111 /* RNNOverlayWindow.h in Headers */,
1288
 				507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */,
1289
 				507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */,
1289
-				50220F48212ABDFD004C2B0A /* RNNReactRootView.h in Headers */,
1290
 				5053CE7F2175FB1900D0386B /* RNNDefaultOptionsHelper.h in Headers */,
1290
 				5053CE7F2175FB1900D0386B /* RNNDefaultOptionsHelper.h in Headers */,
1291
 				2DCD9195200014A900EDC75D /* RNNBridgeManager.h in Headers */,
1291
 				2DCD9195200014A900EDC75D /* RNNBridgeManager.h in Headers */,
1292
 				7B1126A91E2D2B6C00F9B03B /* RNNControllerFactory.h in Headers */,
1292
 				7B1126A91E2D2B6C00F9B03B /* RNNControllerFactory.h in Headers */,
1462
 				5012242721737278000F5F98 /* NullImage.m in Sources */,
1462
 				5012242721737278000F5F98 /* NullImage.m in Sources */,
1463
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
1463
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
1464
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
1464
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
1465
+				5050465521F8F4490035497A /* RNNReactComponentManager.m in Sources */,
1465
 				263905CB1E4C6F440023D7D3 /* SidebarLuvocracyAnimation.m in Sources */,
1466
 				263905CB1E4C6F440023D7D3 /* SidebarLuvocracyAnimation.m in Sources */,
1466
 				50570BEB2063E09B006A1B5C /* RNNTitleViewHelper.m in Sources */,
1467
 				50570BEB2063E09B006A1B5C /* RNNTitleViewHelper.m in Sources */,
1467
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
1468
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
1509
 				50EB4ED82068EBE000D6ED34 /* RNNBackgroundOptions.m in Sources */,
1510
 				50EB4ED82068EBE000D6ED34 /* RNNBackgroundOptions.m in Sources */,
1510
 				507F43CA1FF4F9CC00D9425B /* RNNTopTabOptions.m in Sources */,
1511
 				507F43CA1FF4F9CC00D9425B /* RNNTopTabOptions.m in Sources */,
1511
 				26916C991E4B9E7700D13680 /* RNNReactRootViewCreator.m in Sources */,
1512
 				26916C991E4B9E7700D13680 /* RNNReactRootViewCreator.m in Sources */,
1512
-				50220F49212ABDFD004C2B0A /* RNNReactRootView.m in Sources */,
1513
 				5064495E20DC62B90026709C /* RNNSideMenuSideOptions.m in Sources */,
1513
 				5064495E20DC62B90026709C /* RNNSideMenuSideOptions.m in Sources */,
1514
 				214545251F4DC125006E8DA1 /* RNNUIBarButtonItem.m in Sources */,
1514
 				214545251F4DC125006E8DA1 /* RNNUIBarButtonItem.m in Sources */,
1515
 				263905B81E4C6F440023D7D3 /* UIViewController+MMDrawerController.m in Sources */,
1515
 				263905B81E4C6F440023D7D3 /* UIViewController+MMDrawerController.m in Sources */,

+ 38
- 11
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

62
 	self.store = [OCMockObject partialMockForObject:[[RNNStore alloc] init]];
62
 	self.store = [OCMockObject partialMockForObject:[[RNNStore alloc] init]];
63
 	self.eventEmmiter = [OCMockObject partialMockForObject:[RNNEventEmitter new]];
63
 	self.eventEmmiter = [OCMockObject partialMockForObject:[RNNEventEmitter new]];
64
 	self.overlayManager = [OCMockObject partialMockForObject:[RNNOverlayManager new]];
64
 	self.overlayManager = [OCMockObject partialMockForObject:[RNNOverlayManager new]];
65
-	self.controllerFactory = [OCMockObject partialMockForObject:[[RNNControllerFactory alloc] initWithRootViewCreator:nil eventEmitter:self.eventEmmiter andBridge:nil]];
65
+	self.controllerFactory = [OCMockObject partialMockForObject:[[RNNControllerFactory alloc] initWithRootViewCreator:nil eventEmitter:self.eventEmmiter store:self.store componentManager:nil andBridge:nil]];
66
 	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:self.controllerFactory eventEmitter:self.eventEmmiter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:self.overlayManager mainWindow:_mainWindow];
66
 	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:self.controllerFactory eventEmitter:self.eventEmmiter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:self.overlayManager mainWindow:_mainWindow];
67
 	self.vc1 = [RNNRootViewController new];
67
 	self.vc1 = [RNNRootViewController new];
68
 	self.vc2 = [RNNRootViewController new];
68
 	self.vc2 = [RNNRootViewController new];
126
 	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
126
 	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
127
 	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:creator eventEmitter:nil presenter:presenter options:initialOptions defaultOptions:nil];
127
 	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:creator eventEmitter:nil presenter:presenter options:initialOptions defaultOptions:nil];
128
 	
128
 	
129
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[vc] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
129
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:creator childViewControllers:@[vc] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
130
 	
130
 	
131
 	[vc viewWillAppear:false];
131
 	[vc viewWillAppear:false];
132
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
132
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
213
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
213
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
214
 	NSDictionary* layout = @{};
214
 	NSDictionary* layout = @{};
215
 	
215
 	
216
-	[[self.controllerFactory expect] createLayout:layout saveToStore:self.store];
216
+	[[self.controllerFactory expect] createLayout:layout];
217
 	[self.uut showOverlay:layout completion:^{}];
217
 	[self.uut showOverlay:layout completion:^{}];
218
 	[self.controllerFactory verify];
218
 	[self.controllerFactory verify];
219
 }
219
 }
221
 - (void)testShowOverlay_saveToStore {
221
 - (void)testShowOverlay_saveToStore {
222
 	[self.store setReadyToReceiveCommands:true];
222
 	[self.store setReadyToReceiveCommands:true];
223
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
223
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
224
-	OCMStub([self.controllerFactory createLayout:[OCMArg any] saveToStore:[OCMArg any]]);
224
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]);
225
 	
225
 	
226
-	[[self.controllerFactory expect] createLayout:[OCMArg any] saveToStore:self.store];
226
+	[[self.controllerFactory expect] createLayout:[OCMArg any]];
227
 	[self.uut showOverlay:@{} completion:^{}];
227
 	[self.uut showOverlay:@{} completion:^{}];
228
 	[self.overlayManager verify];
228
 	[self.overlayManager verify];
229
 }
229
 }
231
 - (void)testShowOverlay_withCreatedLayout {
231
 - (void)testShowOverlay_withCreatedLayout {
232
 	[self.store setReadyToReceiveCommands:true];
232
 	[self.store setReadyToReceiveCommands:true];
233
 	UIViewController* layoutVC = [RNNRootViewController new];
233
 	UIViewController* layoutVC = [RNNRootViewController new];
234
-	OCMStub([self.controllerFactory createLayout:[OCMArg any] saveToStore:[OCMArg any]]).andReturn(layoutVC);
234
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(layoutVC);
235
 	
235
 	
236
 	[[self.overlayManager expect] showOverlayWindow:[OCMArg any]];
236
 	[[self.overlayManager expect] showOverlayWindow:[OCMArg any]];
237
 	[self.uut showOverlay:@{} completion:^{}];
237
 	[self.uut showOverlay:@{} completion:^{}];
241
 - (void)testShowOverlay_invokeNavigationCommandEventWithLayout {
241
 - (void)testShowOverlay_invokeNavigationCommandEventWithLayout {
242
 	[self.store setReadyToReceiveCommands:true];
242
 	[self.store setReadyToReceiveCommands:true];
243
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
243
 	OCMStub([self.overlayManager showOverlayWindow:[OCMArg any]]);
244
-	OCMStub([self.controllerFactory createLayout:[OCMArg any] saveToStore:[OCMArg any]]);
244
+	id mockedVC = [OCMockObject partialMockForObject:self.vc1];	
245
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(mockedVC);
245
 	
246
 	
246
 	NSDictionary* layout = @{};
247
 	NSDictionary* layout = @{};
247
 	
248
 	
294
 
295
 
295
 - (void)testSetRoot_setRootViewControllerOnMainWindow {
296
 - (void)testSetRoot_setRootViewControllerOnMainWindow {
296
 	[self.store setReadyToReceiveCommands:true];
297
 	[self.store setReadyToReceiveCommands:true];
297
-	OCMStub([self.controllerFactory createLayout:[OCMArg any] saveToStore:self.store]).andReturn(self.vc1);
298
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(self.vc1);
298
 	
299
 	
299
 	[[self.mainWindow expect] setRootViewController:self.vc1];
300
 	[[self.mainWindow expect] setRootViewController:self.vc1];
300
 	[self.uut setRoot:@{} completion:^{}];
301
 	[self.uut setRoot:@{} completion:^{}];
303
 
304
 
304
 - (void)testSetRoot_removeAllComponentsFromMainWindow {
305
 - (void)testSetRoot_removeAllComponentsFromMainWindow {
305
 	[self.store setReadyToReceiveCommands:true];
306
 	[self.store setReadyToReceiveCommands:true];
306
-	OCMStub([self.controllerFactory createLayout:[OCMArg any] saveToStore:self.store]).andReturn(self.vc1);
307
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(self.vc1);
307
 	
308
 	
308
 	[[self.store expect] removeAllComponentsFromWindow:self.mainWindow];
309
 	[[self.store expect] removeAllComponentsFromWindow:self.mainWindow];
309
 	[self.uut setRoot:@{} completion:^{}];
310
 	[self.uut setRoot:@{} completion:^{}];
311
 }
312
 }
312
 
313
 
313
 - (void)testSetStackRoot_resetStackWithSingleComponent {
314
 - (void)testSetStackRoot_resetStackWithSingleComponent {
314
-	OCMStub([self.controllerFactory createChildrenLayout:[OCMArg any] saveToStore:self.store]).andReturn(@[self.vc2]);
315
+	OCMStub([self.controllerFactory createChildrenLayout:[OCMArg any]]).andReturn(@[self.vc2]);
315
 	[self.store setReadyToReceiveCommands:true];
316
 	[self.store setReadyToReceiveCommands:true];
316
 	[self.uut setStackRoot:@"vc1" children:nil completion:^{
317
 	[self.uut setStackRoot:@"vc1" children:nil completion:^{
317
 		
318
 		
324
 
325
 
325
 - (void)testSetStackRoot_setMultipleChildren {
326
 - (void)testSetStackRoot_setMultipleChildren {
326
 	NSArray* newViewControllers = @[_vc1, _vc3];
327
 	NSArray* newViewControllers = @[_vc1, _vc3];
327
-	OCMStub([self.controllerFactory createChildrenLayout:[OCMArg any] saveToStore:self.store]).andReturn(newViewControllers);
328
+	OCMStub([self.controllerFactory createChildrenLayout:[OCMArg any]]).andReturn(newViewControllers);
328
 	[self.store setReadyToReceiveCommands:true];
329
 	[self.store setReadyToReceiveCommands:true];
329
 	[self.uut setStackRoot:@"vc1" children:nil completion:^{
330
 	[self.uut setStackRoot:@"vc1" children:nil completion:^{
330
 		
331
 		
334
 	XCTAssertTrue([_nvc.viewControllers isEqual:newViewControllers]);
335
 	XCTAssertTrue([_nvc.viewControllers isEqual:newViewControllers]);
335
 }
336
 }
336
 
337
 
338
+- (void)testSetRoot_waitForRenderTrue {
339
+	[self.store setReadyToReceiveCommands:true];
340
+	self.vc1.options = [[RNNNavigationOptions alloc] initEmptyOptions];
341
+	self.vc1.options.animations.setRoot.waitForRender = [[Bool alloc] initWithBOOL:YES];
342
+	
343
+	id mockedVC = [OCMockObject partialMockForObject:self.vc1];
344
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(mockedVC);
345
+	
346
+	[[mockedVC expect] renderTreeAndWait:YES perform:[OCMArg any]];
347
+	[self.uut setRoot:@{} completion:^{}];
348
+	[mockedVC verify];
349
+}
350
+
351
+- (void)testSetRoot_waitForRenderFalse {
352
+	[self.store setReadyToReceiveCommands:true];
353
+	self.vc1.options = [[RNNNavigationOptions alloc] initEmptyOptions];
354
+	self.vc1.options.animations.setRoot.waitForRender = [[Bool alloc] initWithBOOL:NO];
355
+	
356
+	id mockedVC = [OCMockObject partialMockForObject:self.vc1];
357
+	OCMStub([self.controllerFactory createLayout:[OCMArg any]]).andReturn(mockedVC);
358
+	
359
+	[[mockedVC expect] renderTreeAndWait:NO perform:[OCMArg any]];
360
+	[self.uut setRoot:@{} completion:^{}];
361
+	[mockedVC verify];
362
+}
363
+
337
 @end
364
 @end

+ 11
- 11
lib/ios/ReactNativeNavigationTests/RNNControllerFactoryTest.m View File

23
 	[super setUp];
23
 	[super setUp];
24
 	self.creator = nil;
24
 	self.creator = nil;
25
 	self.store = [RNNStore new];
25
 	self.store = [RNNStore new];
26
-	self.factory = [[RNNControllerFactory alloc] initWithRootViewCreator:self.creator eventEmitter:nil andBridge:nil];
26
+	self.factory = [[RNNControllerFactory alloc] initWithRootViewCreator:self.creator eventEmitter:nil store:self.store componentManager:nil andBridge:nil];
27
 }
27
 }
28
 
28
 
29
 - (void)tearDown {
29
 - (void)tearDown {
31
 }
31
 }
32
 
32
 
33
 - (void)testCreateLayout_EmptyLayout {
33
 - (void)testCreateLayout_EmptyLayout {
34
-	XCTAssertThrows([self.factory createLayout:@{} saveToStore:self.store]);
34
+	XCTAssertThrows([self.factory createLayout:@{}]);
35
 }
35
 }
36
 
36
 
37
 - (void)testCreateLayout_ComponentLayout {
37
 - (void)testCreateLayout_ComponentLayout {
39
 							 @"type": @"Component",
39
 							 @"type": @"Component",
40
 							 @"data": @{},
40
 							 @"data": @{},
41
 							 @"children": @[]};
41
 							 @"children": @[]};
42
-	id ans = [self.factory createLayout:layout saveToStore:self.store];
42
+	id ans = [self.factory createLayout:layout];
43
 	XCTAssertTrue([ans isMemberOfClass:[RNNRootViewController class]]);
43
 	XCTAssertTrue([ans isMemberOfClass:[RNNRootViewController class]]);
44
 }
44
 }
45
 
45
 
52
 							  @"type": @"ExternalComponent",
52
 							  @"type": @"ExternalComponent",
53
 							  @"data": @{@"name": @"externalComponent"},
53
 							  @"data": @{@"name": @"externalComponent"},
54
 							  @"children": @[]};
54
 							  @"children": @[]};
55
-	id ans = [self.factory createLayout:layout saveToStore:self.store];
55
+	id ans = [self.factory createLayout:layout];
56
 	XCTAssertTrue([ans isMemberOfClass:[RNNRootViewController class]]);
56
 	XCTAssertTrue([ans isMemberOfClass:[RNNRootViewController class]]);
57
 }
57
 }
58
 
58
 
61
 							 @"type": @"Stack",
61
 							 @"type": @"Stack",
62
 							 @"data": @{},
62
 							 @"data": @{},
63
 							 @"children": @[]};
63
 							 @"children": @[]};
64
-	id ans = [self.factory createLayout:layout saveToStore:self.store];
64
+	id ans = [self.factory createLayout:layout];
65
 	XCTAssertTrue([ans isMemberOfClass:[RNNNavigationController class]]);
65
 	XCTAssertTrue([ans isMemberOfClass:[RNNNavigationController class]]);
66
 }
66
 }
67
 
67
 
78
 									   @"type": @"Component",
78
 									   @"type": @"Component",
79
 									   @"data": @{},
79
 									   @"data": @{},
80
 									   @"children": @[]}]};
80
 									   @"children": @[]}]};
81
-	id ans = [self.factory createLayout:layout saveToStore:self.store];
81
+	id ans = [self.factory createLayout:layout];
82
 	XCTAssertTrue([ans isMemberOfClass:[RNNSplitViewController class]]);
82
 	XCTAssertTrue([ans isMemberOfClass:[RNNSplitViewController class]]);
83
 }
83
 }
84
 
84
 
91
 									   @"type": @"Component",
91
 									   @"type": @"Component",
92
 									   @"data": @{},
92
 									   @"data": @{},
93
 									   @"children": @[]}]};
93
 									   @"children": @[]}]};
94
-	RNNNavigationController* ans = (RNNNavigationController*) [self.factory createLayout:layout saveToStore:self.store];
94
+	RNNNavigationController* ans = (RNNNavigationController*) [self.factory createLayout:layout];
95
 	
95
 	
96
 	XCTAssertTrue([ans isMemberOfClass:[RNNNavigationController class]]);
96
 	XCTAssertTrue([ans isMemberOfClass:[RNNNavigationController class]]);
97
 	XCTAssertTrue(ans.childViewControllers.count == 1);
97
 	XCTAssertTrue(ans.childViewControllers.count == 1);
112
 												 @"type": @"Component",
112
 												 @"type": @"Component",
113
 												 @"data": @{},
113
 												 @"data": @{},
114
 												 @"children": @[]}]}]};
114
 												 @"children": @[]}]}]};
115
-	RNNTabBarController* tabBar = (RNNTabBarController*) [self.factory createLayout:layout saveToStore:self.store];
115
+	RNNTabBarController* tabBar = (RNNTabBarController*) [self.factory createLayout:layout];
116
 	
116
 	
117
 	XCTAssertTrue([tabBar isMemberOfClass:[RNNTabBarController class]]);
117
 	XCTAssertTrue([tabBar isMemberOfClass:[RNNTabBarController class]]);
118
 	XCTAssertTrue(tabBar.childViewControllers.count == 1);
118
 	XCTAssertTrue(tabBar.childViewControllers.count == 1);
137
 												 @"type": @"Component",
137
 												 @"type": @"Component",
138
 												 @"data": @{},
138
 												 @"data": @{},
139
 												 @"children": @[]}]}]};
139
 												 @"children": @[]}]}]};
140
-	RNNTopTabsViewController* tabBar = (RNNTopTabsViewController*) [self.factory createLayout:layout saveToStore:self.store];
140
+	RNNTopTabsViewController* tabBar = (RNNTopTabsViewController*) [self.factory createLayout:layout];
141
 	
141
 	
142
 	XCTAssertTrue([tabBar isMemberOfClass:[RNNTopTabsViewController class]]);
142
 	XCTAssertTrue([tabBar isMemberOfClass:[RNNTopTabsViewController class]]);
143
 }
143
 }
171
 												 @"type": @"Component",
171
 												 @"type": @"Component",
172
 												 @"data": @{},
172
 												 @"data": @{},
173
 												 @"children": @[]}]}]};
173
 												 @"children": @[]}]}]};
174
-	RNNSideMenuController *ans = (RNNSideMenuController*) [self.factory createLayout:layout saveToStore:self.store];
174
+	RNNSideMenuController *ans = (RNNSideMenuController*) [self.factory createLayout:layout];
175
 	XCTAssertTrue([ans isMemberOfClass:[RNNSideMenuController class]]);
175
 	XCTAssertTrue([ans isMemberOfClass:[RNNSideMenuController class]]);
176
 	XCTAssertTrue([ans isKindOfClass:[UIViewController class]]);
176
 	XCTAssertTrue([ans isKindOfClass:[UIViewController class]]);
177
 	XCTAssertTrue([ans.center isMemberOfClass:[RNNSideMenuChildVC class]]);
177
 	XCTAssertTrue([ans.center isMemberOfClass:[RNNSideMenuChildVC class]]);
194
 							 @"type": @"Component",
194
 							 @"type": @"Component",
195
 							 @"data": @{},
195
 							 @"data": @{},
196
 							 @"children": @[]};
196
 							 @"children": @[]};
197
-	UIViewController *ans = [self.factory createLayout:layout saveToStore:self.store];
197
+	UIViewController *ans = [self.factory createLayout:layout];
198
 	
198
 	
199
 	UIViewController *storeAns = [self.store findComponentForId:componentId];
199
 	UIViewController *storeAns = [self.store findComponentForId:componentId];
200
 	XCTAssertEqualObjects(ans, storeAns);
200
 	XCTAssertEqualObjects(ans, storeAns);

+ 6
- 4
lib/ios/ReactNativeNavigationTests/RNNNavigationControllerTest.m View File

2
 #import <OCMock/OCMock.h>
2
 #import <OCMock/OCMock.h>
3
 #import "RNNNavigationController.h"
3
 #import "RNNNavigationController.h"
4
 #import "RNNRootViewController.h"
4
 #import "RNNRootViewController.h"
5
+#import "RNNTestRootViewCreator.h"
5
 
6
 
6
 @interface RNNNavigationControllerTest : XCTestCase
7
 @interface RNNNavigationControllerTest : XCTestCase
7
 
8
 
15
 	RNNRootViewController* _vc2;
16
 	RNNRootViewController* _vc2;
16
 	UIViewController* _vc3;
17
 	UIViewController* _vc3;
17
 	RNNNavigationOptions* _options;
18
 	RNNNavigationOptions* _options;
19
+	RNNTestRootViewCreator* _creator;
18
 }
20
 }
19
 
21
 
20
 - (void)setUp {
22
 - (void)setUp {
21
     [super setUp];
23
     [super setUp];
22
-	
24
+	_creator = [[RNNTestRootViewCreator alloc] init];
23
 	_vc1 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[OCMockObject partialMockForObject:[[RNNViewControllerPresenter alloc] init]] options:[[RNNNavigationOptions alloc] initEmptyOptions]  defaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
25
 	_vc1 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[OCMockObject partialMockForObject:[[RNNViewControllerPresenter alloc] init]] options:[[RNNNavigationOptions alloc] initEmptyOptions]  defaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
24
 	_vc2 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[[RNNViewControllerPresenter alloc] init] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
26
 	_vc2 = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[[RNNViewControllerPresenter alloc] init] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
25
 	_vc2Mock = [OCMockObject partialMockForObject:_vc2];
27
 	_vc2Mock = [OCMockObject partialMockForObject:_vc2];
26
 	_vc3 = [UIViewController new];
28
 	_vc3 = [UIViewController new];
27
 	_options = [OCMockObject partialMockForObject:[[RNNNavigationOptions alloc] initEmptyOptions]];
29
 	_options = [OCMockObject partialMockForObject:[[RNNNavigationOptions alloc] initEmptyOptions]];
28
-	self.uut = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[_vc1, _vc2] options:_options defaultOptions:nil presenter:[OCMockObject partialMockForObject:[[RNNNavigationControllerPresenter alloc] init]]];
30
+	self.uut = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[_vc1, _vc2] options:_options defaultOptions:nil presenter:[OCMockObject partialMockForObject:[[RNNNavigationControllerPresenter alloc] init]]];
29
 }
31
 }
30
 
32
 
31
 - (void)testInitWithLayoutInfo_shouldBindPresenter {
33
 - (void)testInitWithLayoutInfo_shouldBindPresenter {
33
 }
35
 }
34
 
36
 
35
 - (void)testInitWithLayoutInfo_shouldSetMultipleViewControllers {
37
 - (void)testInitWithLayoutInfo_shouldSetMultipleViewControllers {
36
-	self.uut = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[_vc1, _vc2] options:[[RNNNavigationOptions alloc] initWithDict:@{}] defaultOptions:nil presenter:[[RNNViewControllerPresenter alloc] init]];
38
+	self.uut = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[_vc1, _vc2] options:[[RNNNavigationOptions alloc] initWithDict:@{}] defaultOptions:nil presenter:[[RNNViewControllerPresenter alloc] init]];
37
 	XCTAssertTrue(self.uut.viewControllers.count == 2);
39
 	XCTAssertTrue(self.uut.viewControllers.count == 2);
38
 }
40
 }
39
 
41
 
157
 }
159
 }
158
 
160
 
159
 - (RNNNavigationController *)createNavigationControllerWithOptions:(RNNNavigationOptions *)options {
161
 - (RNNNavigationController *)createNavigationControllerWithOptions:(RNNNavigationOptions *)options {
160
-	return [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[_vc1] options:options defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
162
+	return [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[_vc1] options:options defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
161
 }
163
 }
162
 
164
 
163
 @end
165
 @end

+ 5
- 5
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

415
 -(void)testRightButtonsWithTitle_withoutStyle {
415
 -(void)testRightButtonsWithTitle_withoutStyle {
416
 	self.options.topBar.rightButtons = @[@{@"id": @"testId", @"text": @"test"}];
416
 	self.options.topBar.rightButtons = @[@{@"id": @"testId", @"text": @"test"}];
417
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
417
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
418
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
418
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
419
 
419
 
420
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.rightBarButtonItems objectAtIndex:0];
420
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.rightBarButtonItems objectAtIndex:0];
421
 	NSString* expectedButtonId = @"testId";
421
 	NSString* expectedButtonId = @"testId";
430
 
430
 
431
 	self.options.topBar.rightButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
431
 	self.options.topBar.rightButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
432
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
432
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
433
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
433
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
434
 
434
 
435
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.rightBarButtonItems objectAtIndex:0];
435
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.rightBarButtonItems objectAtIndex:0];
436
 	NSString* expectedButtonId = @"testId";
436
 	NSString* expectedButtonId = @"testId";
446
 -(void)testLeftButtonsWithTitle_withoutStyle {
446
 -(void)testLeftButtonsWithTitle_withoutStyle {
447
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test"}];
447
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test"}];
448
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
448
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
449
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
449
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
450
 
450
 
451
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
451
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
452
 	NSString* expectedButtonId = @"testId";
452
 	NSString* expectedButtonId = @"testId";
461
 
461
 
462
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
462
 	self.options.topBar.leftButtons = @[@{@"id": @"testId", @"text": @"test", @"enabled": @false, @"buttonColor": inputColor, @"buttonFontSize": @22, @"buttonFontWeight": @"800"}];
463
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
463
 	self.uut = [[RNNRootViewController alloc] initWithLayoutInfo:nil rootViewCreator:nil eventEmitter:nil presenter:[RNNViewControllerPresenter new] options:self.options defaultOptions:nil];
464
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
464
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:_creator childViewControllers:@[self.uut] options:nil defaultOptions:nil presenter:nil];
465
 
465
 
466
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
466
 	RNNUIBarButtonItem* button = (RNNUIBarButtonItem*)[nav.topViewController.navigationItem.leftBarButtonItems objectAtIndex:0];
467
 	NSString* expectedButtonId = @"testId";
467
 	NSString* expectedButtonId = @"testId";
565
 
565
 
566
 
566
 
567
 - (RNNNavigationController *)createNavigationController {
567
 - (RNNNavigationController *)createNavigationController {
568
-	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil childViewControllers:@[self.uut] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
568
+	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:nil childViewControllers:@[self.uut] options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:nil presenter:[[RNNNavigationControllerPresenter alloc] init]];
569
 	
569
 	
570
 	return nav;
570
 	return nav;
571
 }
571
 }

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNTestRootViewCreator.m View File

2
 
2
 
3
 @implementation RNNTestRootViewCreator
3
 @implementation RNNTestRootViewCreator
4
 
4
 
5
-- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId {
5
+- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
6
 	UIView *view = [[UIView alloc] init];
6
 	UIView *view = [[UIView alloc] init];
7
 	return view;
7
 	return view;
8
 }
8
 }

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m View File

70
 
70
 
71
 - (void)testBindViewControllerShouldCreateNavigationButtonsCreator {
71
 - (void)testBindViewControllerShouldCreateNavigationButtonsCreator {
72
 	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
72
 	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
73
-	[presenter bindViewController:self.bindedViewController viewCreator:nil];
73
+	[presenter bindViewController:self.bindedViewController];
74
 	XCTAssertNotNil(presenter.navigationButtons);
74
 	XCTAssertNotNil(presenter.navigationButtons);
75
 }
75
 }
76
 
76
 

+ 1
- 0
lib/ios/UIViewController+RNNOptions.m View File

43
 			}
43
 			}
44
 			search.hidesNavigationBarDuringPresentation = hideNavBarOnFocusSearchBar;
44
 			search.hidesNavigationBarDuringPresentation = hideNavBarOnFocusSearchBar;
45
 			self.navigationItem.searchController = search;
45
 			self.navigationItem.searchController = search;
46
+			[self.navigationItem setHidesSearchBarWhenScrolling:NO];
46
 			
47
 			
47
 			// Fixes #3450, otherwise, UIKit will infer the presentation context to be the root most view controller
48
 			// Fixes #3450, otherwise, UIKit will infer the presentation context to be the root most view controller
48
 			self.definesPresentationContext = YES;
49
 			self.definesPresentationContext = YES;

+ 2
- 1
playground/src/app.js View File

50
             from: 0,
50
             from: 0,
51
             to: 1,
51
             to: 1,
52
             duration: 300
52
             duration: 300
53
-          }
53
+          },
54
+          waitForRender: true
54
         },
55
         },
55
         _push: {
56
         _push: {
56
           topBar: {
57
           topBar: {