Browse Source

Handle adding and removing components from registry manually by presenters (#4942)

Yogev Ben David 5 years ago
parent
commit
ac60d2fe6a
No account linked to committer's email address

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

4
 
4
 
5
 @property (nonatomic, weak) id bindedViewController;
5
 @property (nonatomic, weak) id bindedViewController;
6
 
6
 
7
+@property (nonatomic, strong) NSString* bindedComponentId;
8
+
7
 - (void)bindViewController:(UIViewController *)bindedViewController;
9
 - (void)bindViewController:(UIViewController *)bindedViewController;
8
 
10
 
9
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions;
11
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions;

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

10
 
10
 
11
 @implementation RNNBasePresenter
11
 @implementation RNNBasePresenter
12
 
12
 
13
-- (instancetype)initWithcomponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
13
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
14
 	self = [super init];
14
 	self = [super init];
15
 	self.componentRegistry = componentRegistry;
15
 	self.componentRegistry = componentRegistry;
16
 	return self;
16
 	return self;
17
 }
17
 }
18
 
18
 
19
-- (void)bindViewController:(UIViewController *)bindedViewController {
19
+- (void)bindViewController:(UIViewController<RNNLayoutProtocol> *)bindedViewController {
20
+	self.bindedComponentId = bindedViewController.layoutInfo.componentId;
20
 	_bindedViewController = bindedViewController;
21
 	_bindedViewController = bindedViewController;
21
 }
22
 }
22
 
23
 

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

92
 
92
 
93
 - (void)onJavaScriptWillLoad {
93
 - (void)onJavaScriptWillLoad {
94
 	[_store clean];
94
 	[_store clean];
95
-	[_componentRegistry clean];
95
+	[_componentRegistry clear];
96
 }
96
 }
97
 
97
 
98
 - (void)onJavaScriptLoaded {
98
 - (void)onJavaScriptLoaded {

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

115
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
115
 - (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
116
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
116
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
117
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
117
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
118
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithcomponentRegistry:_componentRegistry];
118
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];
119
 	
119
 	
120
 	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];
121
 	
121
 	
137
 
137
 
138
 
138
 
139
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
139
 - (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
140
-	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithcomponentRegistry:_componentRegistry];
140
+	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];
141
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
141
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
142
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
142
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
143
 	
143
 	

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

7
 
7
 
8
 @property (nonatomic, strong) InteractivePopGestureDelegate *interactivePopGestureDelegate;
8
 @property (nonatomic, strong) InteractivePopGestureDelegate *interactivePopGestureDelegate;
9
 
9
 
10
-- (instancetype)initWithcomponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
10
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
11
 
11
 
12
 - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options;
12
 - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options;
13
 
13
 

+ 11
- 10
lib/ios/RNNNavigationControllerPresenter.m View File

13
 @end
13
 @end
14
 @implementation RNNNavigationControllerPresenter
14
 @implementation RNNNavigationControllerPresenter
15
 
15
 
16
-- (instancetype)initWithcomponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
16
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
17
 	self = [super init];
17
 	self = [super init];
18
 	_componentRegistry = componentRegistry;
18
 	_componentRegistry = componentRegistry;
19
 	return self;
19
 	return self;
20
 }
20
 }
21
 
21
 
22
-- (void)bindViewController:(UIViewController *)bindedViewController {
23
-	self.bindedViewController = bindedViewController;
24
-}
25
-
26
 - (void)applyOptions:(RNNNavigationOptions *)options {
22
 - (void)applyOptions:(RNNNavigationOptions *)options {
27
 	[super applyOptions:options];
23
 	[super applyOptions:options];
28
 	
24
 	
179
 		readyBlock = nil;
175
 		readyBlock = nil;
180
 	}
176
 	}
181
 	if (options.topBar.component.name.hasValue) {
177
 	if (options.topBar.component.name.hasValue) {
182
-		RCTRootView *reactView = [_componentRegistry createComponentIfNotExists:options.topBar.component parentComponentId:navigationController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
178
+		NSString* currentChildComponentId = [navigationController getCurrentChild].layoutInfo.componentId;
179
+		RCTRootView *reactView = [_componentRegistry createComponentIfNotExists:options.topBar.component parentComponentId:currentChildComponentId reactViewReadyBlock:readyBlock];
183
 		
180
 		
184
 		if (_customTopBar) {
181
 		if (_customTopBar) {
185
 			[_customTopBar removeFromSuperview];
182
 			[_customTopBar removeFromSuperview];
190
 		[navigationController.navigationBar addSubview:_customTopBar];
187
 		[navigationController.navigationBar addSubview:_customTopBar];
191
 	} else {
188
 	} else {
192
 		[_customTopBar removeFromSuperview];
189
 		[_customTopBar removeFromSuperview];
190
+		_customTopBar = nil;
193
 		if (readyBlock) {
191
 		if (readyBlock) {
194
 			readyBlock();
192
 			readyBlock();
195
 		}
193
 		}
203
 		readyBlock = nil;
201
 		readyBlock = nil;
204
 	}
202
 	}
205
 	if (options.topBar.background.component.name.hasValue) {
203
 	if (options.topBar.background.component.name.hasValue) {
206
-		RCTRootView *reactView = [_componentRegistry createComponentIfNotExists:options.topBar.background.component parentComponentId:navigationController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
204
+		NSString* currentChildComponentId = [navigationController getCurrentChild].layoutInfo.componentId;
205
+		RCTRootView *reactView = [_componentRegistry createComponentIfNotExists:options.topBar.background.component parentComponentId:currentChildComponentId reactViewReadyBlock:readyBlock];
207
 		
206
 		
208
 		if (_customTopBarBackground) {
207
 		if (_customTopBarBackground) {
209
 			[_customTopBarBackground removeFromSuperview];
208
 			[_customTopBarBackground removeFromSuperview];
210
 		}
209
 		}
211
-		_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
210
+		RNNCustomTitleView* customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
211
+		_customTopBarBackground = customTopBarBackground;
212
+		
212
 		[navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
213
 		[navigationController.navigationBar insertSubview:_customTopBarBackground atIndex:1];
213
 	} else {
214
 	} else {
214
 		[_customTopBarBackground removeFromSuperview];
215
 		[_customTopBarBackground removeFromSuperview];
216
+		_customTopBarBackground = nil;
215
 		if (readyBlock) {
217
 		if (readyBlock) {
216
 			readyBlock();
218
 			readyBlock();
217
 		}
219
 		}
219
 }
221
 }
220
 
222
 
221
 - (void)dealloc {
223
 - (void)dealloc {
222
-	RNNNavigationController* navigationController = self.bindedViewController;
223
-	[_componentRegistry removeComponent:navigationController.layoutInfo.componentId];
224
+	[_componentRegistry removeComponent:self.bindedComponentId];
224
 }
225
 }
225
 
226
 
226
 @end
227
 @end

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

12
 
12
 
13
 - (void)removeComponent:(NSString *)componentId;
13
 - (void)removeComponent:(NSString *)componentId;
14
 
14
 
15
-- (void)clean;
15
+- (void)clearComponentsForParentId:(NSString *)parentComponentId;
16
+
17
+- (void)clear;
16
 
18
 
17
 @end
19
 @end

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

12
 - (instancetype)initWithCreator:(id<RNNRootViewCreator>)creator {
12
 - (instancetype)initWithCreator:(id<RNNRootViewCreator>)creator {
13
 	self = [super init];
13
 	self = [super init];
14
 	_creator = creator;
14
 	_creator = creator;
15
-	_componentStore = [NSMapTable strongToWeakObjectsMapTable];
15
+	_componentStore = [NSMapTable new];
16
 	return self;
16
 	return self;
17
 }
17
 }
18
 
18
 
38
 	return [_componentStore objectForKey:parentComponentId];;
38
 	return [_componentStore objectForKey:parentComponentId];;
39
 }
39
 }
40
 
40
 
41
+- (void)clearComponentsForParentId:(NSString *)parentComponentId {
42
+	[_componentStore removeObjectForKey:parentComponentId];;
43
+}
44
+
41
 - (void)removeComponent:(NSString *)componentId {
45
 - (void)removeComponent:(NSString *)componentId {
42
 	if ([_componentStore objectForKey:componentId]) {
46
 	if ([_componentStore objectForKey:componentId]) {
43
 		[_componentStore removeObjectForKey:componentId];
47
 		[_componentStore removeObjectForKey:componentId];
44
 	}
48
 	}
45
 }
49
 }
46
 
50
 
47
-- (void)clean {
51
+- (void)clear {
48
 	[_componentStore removeAllObjects];
52
 	[_componentStore removeAllObjects];
49
 }
53
 }
50
 
54
 

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

30
 }
30
 }
31
 
31
 
32
 - (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {
32
 - (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {
33
-	_rootViewDidChangeIntrinsicSize = rootViewDidChangeIntrinsicSize;
34
-	self.delegate = self;
33
+		_rootViewDidChangeIntrinsicSize = rootViewDidChangeIntrinsicSize;
34
+		self.delegate = self;
35
 }
35
 }
36
 
36
 
37
 - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
37
 - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {

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

5
 
5
 
6
 @implementation RNNSplitViewControllerPresenter
6
 @implementation RNNSplitViewControllerPresenter
7
 
7
 
8
-- (void)bindViewController:(UISplitViewController *)bindedViewController viewCreator:(id<RNNRootViewCreator>)creator {
9
-	self.bindedViewController = bindedViewController;
10
-}
11
-
12
 - (void)applyOptions:(RNNNavigationOptions *)options {
8
 - (void)applyOptions:(RNNNavigationOptions *)options {
13
 	[super applyOptions:options];
9
 	[super applyOptions:options];
14
 	
10
 	

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

36
 	self.backButton = [[RNNBackButtonOptions alloc] initWithDict:dict[@"backButton"]];
36
 	self.backButton = [[RNNBackButtonOptions alloc] initWithDict:dict[@"backButton"]];
37
 	self.leftButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"leftButtonStyle"]];
37
 	self.leftButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"leftButtonStyle"]];
38
 	self.rightButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"rightButtonStyle"]];
38
 	self.rightButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"rightButtonStyle"]];
39
+	self.component = [[RNNComponentOptions alloc] initWithDict:dict[@"component"]];
39
 	
40
 	
40
 	if (self.leftButtonColor.hasValue) {
41
 	if (self.leftButtonColor.hasValue) {
41
 		self.leftButtonStyle.color = self.leftButtonColor;
42
 		self.leftButtonStyle.color = self.leftButtonColor;

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

4
 
4
 
5
 @interface RNNViewControllerPresenter : RNNBasePresenter
5
 @interface RNNViewControllerPresenter : RNNBasePresenter
6
 
6
 
7
-- (instancetype)initWithcomponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
7
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
8
 
8
 
9
 - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
9
 - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
10
 
10
 

+ 9
- 4
lib/ios/RNNViewControllerPresenter.m View File

26
 	return self;
26
 	return self;
27
 }
27
 }
28
 
28
 
29
-- (instancetype)initWithcomponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
29
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
30
 	self = [self init];
30
 	self = [self init];
31
 	_componentRegistry = componentRegistry;
31
 	_componentRegistry = componentRegistry;
32
 	return self;
32
 	return self;
33
 }
33
 }
34
 
34
 
35
-- (void)bindViewController:(UIViewController *)bindedViewController {
36
-	self.bindedViewController = bindedViewController;
35
+- (void)bindViewController:(UIViewController<RNNLayoutProtocol> *)bindedViewController {
36
+	[super bindViewController:bindedViewController];
37
 	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.bindedViewController componentRegistry:_componentRegistry];
37
 	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.bindedViewController componentRegistry:_componentRegistry];
38
 }
38
 }
39
 
39
 
175
 	if (options.topBar.title.component.name.hasValue) {
175
 	if (options.topBar.title.component.name.hasValue) {
176
 		_customTitleView = (RNNReactView*)[_componentRegistry createComponentIfNotExists:options.topBar.title.component parentComponentId:viewController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
176
 		_customTitleView = (RNNReactView*)[_componentRegistry createComponentIfNotExists:options.topBar.title.component parentComponentId:viewController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
177
 		_customTitleView.backgroundColor = UIColor.clearColor;
177
 		_customTitleView.backgroundColor = UIColor.clearColor;
178
+		
178
 		NSString* alignment = [options.topBar.title.component.alignment getWithDefaultValue:@""];
179
 		NSString* alignment = [options.topBar.title.component.alignment getWithDefaultValue:@""];
179
 		[_customTitleView setAlignment:alignment];
180
 		[_customTitleView setAlignment:alignment];
181
+		
180
 		BOOL isCenter = [alignment isEqualToString:@"center"];
182
 		BOOL isCenter = [alignment isEqualToString:@"center"];
181
 		__weak RNNReactView *weakTitleView = _customTitleView;
183
 		__weak RNNReactView *weakTitleView = _customTitleView;
182
 		CGRect frame = viewController.navigationController.navigationBar.bounds;
184
 		CGRect frame = viewController.navigationController.navigationBar.bounds;
183
-		[_customTitleView setFrame:frame];
184
 		[_customTitleView setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicContentSize) {
185
 		[_customTitleView setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicContentSize) {
185
 			if (isCenter) {
186
 			if (isCenter) {
186
 				[weakTitleView setFrame:CGRectMake(0, 0, intrinsicContentSize.width, intrinsicContentSize.height)];
187
 				[weakTitleView setFrame:CGRectMake(0, 0, intrinsicContentSize.width, intrinsicContentSize.height)];
214
 	}
215
 	}
215
 }
216
 }
216
 
217
 
218
+- (void)dealloc {
219
+	[_componentRegistry clearComponentsForParentId:self.bindedComponentId];
220
+}
221
+
217
 - (void)cleanReactLeftovers {
222
 - (void)cleanReactLeftovers {
218
 	_customTitleView = nil;
223
 	_customTitleView = nil;
219
 }
224
 }

+ 3
- 2
lib/ios/ReactNativeNavigationTests/RNNBasePresenterTest.m View File

2
 #import "RNNBasePresenter.h"
2
 #import "RNNBasePresenter.h"
3
 #import <OCMock/OCMock.h>
3
 #import <OCMock/OCMock.h>
4
 #import "UIViewController+RNNOptions.h"
4
 #import "UIViewController+RNNOptions.h"
5
+#import "RNNRootViewController.h"
5
 
6
 
6
 @interface RNNBottomTabPresenterTest : XCTestCase
7
 @interface RNNBottomTabPresenterTest : XCTestCase
7
 
8
 
8
 @property (nonatomic, strong) RNNBasePresenter *uut;
9
 @property (nonatomic, strong) RNNBasePresenter *uut;
9
 @property (nonatomic, strong) RNNNavigationOptions *options;
10
 @property (nonatomic, strong) RNNNavigationOptions *options;
10
-@property (nonatomic, strong) UIViewController* bindedViewController;
11
+@property (nonatomic, strong) RNNRootViewController* bindedViewController;
11
 @property (nonatomic, strong) id mockBindedViewController;
12
 @property (nonatomic, strong) id mockBindedViewController;
12
 
13
 
13
 @end
14
 @end
17
 - (void)setUp {
18
 - (void)setUp {
18
     [super setUp];
19
     [super setUp];
19
     self.uut = [[RNNBasePresenter alloc] init];
20
     self.uut = [[RNNBasePresenter alloc] init];
20
-	self.bindedViewController = [UIViewController new];
21
+	  self.bindedViewController = [RNNRootViewController new];
21
     self.mockBindedViewController = [OCMockObject partialMockForObject:self.bindedViewController];
22
     self.mockBindedViewController = [OCMockObject partialMockForObject:self.bindedViewController];
22
     [self.uut bindViewController:self.mockBindedViewController];
23
     [self.uut bindViewController:self.mockBindedViewController];
23
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
24
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];

+ 2
- 1
lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m View File

2
 #import <OCMock/OCMock.h>
2
 #import <OCMock/OCMock.h>
3
 #import "RNNTabBarPresenter.h"
3
 #import "RNNTabBarPresenter.h"
4
 #import "UITabBarController+RNNOptions.h"
4
 #import "UITabBarController+RNNOptions.h"
5
+#import "RNNTabBarController.h"
5
 
6
 
6
 @interface RNNTabBarPresenterTest : XCTestCase
7
 @interface RNNTabBarPresenterTest : XCTestCase
7
 
8
 
16
 - (void)setUp {
17
 - (void)setUp {
17
     [super setUp];
18
     [super setUp];
18
 	self.uut = [[RNNTabBarPresenter alloc] init];
19
 	self.uut = [[RNNTabBarPresenter alloc] init];
19
-	self.bindedViewController = [OCMockObject partialMockForObject:[UITabBarController new]];
20
+	self.bindedViewController = [OCMockObject partialMockForObject:[RNNTabBarController new]];
20
 	[self.uut bindViewController:self.bindedViewController];
21
 	[self.uut bindViewController:self.bindedViewController];
21
 	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
22
 	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
22
 }
23
 }

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

10
 @property (nonatomic, strong) RNNViewControllerPresenter *uut;
10
 @property (nonatomic, strong) RNNViewControllerPresenter *uut;
11
 @property (nonatomic, strong) RNNNavigationOptions *options;
11
 @property (nonatomic, strong) RNNNavigationOptions *options;
12
 @property (nonatomic, strong) UIViewController *bindedViewController;
12
 @property (nonatomic, strong) UIViewController *bindedViewController;
13
+@property (nonatomic, strong) RNNReactComponentRegistry *componentRegistry;
13
 
14
 
14
 @end
15
 @end
15
 
16
 
17
 
18
 
18
 - (void)setUp {
19
 - (void)setUp {
19
     [super setUp];
20
     [super setUp];
20
-	self.uut = [[RNNViewControllerPresenter alloc] init];
21
+	self.componentRegistry = [OCMockObject partialMockForObject:[RNNReactComponentRegistry new]];
22
+	self.uut = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:self.componentRegistry];
21
 	self.bindedViewController = [OCMockObject partialMockForObject:[RNNRootViewController new]];
23
 	self.bindedViewController = [OCMockObject partialMockForObject:[RNNRootViewController new]];
22
 	[self.uut bindViewController:self.bindedViewController];
24
 	[self.uut bindViewController:self.bindedViewController];
23
 	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
25
 	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
132
     [(id)self.bindedViewController verify];
134
     [(id)self.bindedViewController verify];
133
 }
135
 }
134
 
136
 
137
+- (void)testReactViewShouldBeReleasedOnDealloc {
138
+	RNNRootViewController* bindViewController = [RNNRootViewController new];
139
+	bindViewController.layoutInfo = [self createLayoutInfoWithComponentId:@"componentId"];
140
+	[self.uut bindViewController:bindViewController];
141
+	
142
+	self.options.topBar.title.component = [[RNNComponentOptions alloc] initWithDict:@{@"name": @"componentName"}];
143
+	
144
+	[[(id)self.componentRegistry expect] clearComponentsForParentId:self.uut.bindedComponentId];
145
+	self.uut = nil;
146
+	[(id)self.componentRegistry verify];
147
+}
148
+
149
+- (void)testBindViewControllerShouldSetBindedComponentId {
150
+	RNNRootViewController* bindViewController = [RNNRootViewController new];
151
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] init];
152
+	layoutInfo.componentId = @"componentId";
153
+	bindViewController.layoutInfo = layoutInfo;
154
+	
155
+	[self.uut bindViewController:bindViewController];
156
+	XCTAssertEqual(self.uut.bindedComponentId, @"componentId");
157
+}
158
+
159
+- (void)testRenderComponentsCreateReactViewWithBindedComponentId {
160
+	RNNRootViewController* bindedViewController = [RNNRootViewController new];
161
+	RNNLayoutInfo* layoutInfo = [self createLayoutInfoWithComponentId:@"componentId"];
162
+	bindedViewController.layoutInfo = layoutInfo;
163
+	
164
+	[self.uut bindViewController:bindedViewController];
165
+	
166
+	self.options.topBar.title.component = [[RNNComponentOptions alloc] initWithDict:@{@"name": @"titleComponent"}];
167
+	
168
+	[[(id)self.componentRegistry expect] createComponentIfNotExists:self.options.topBar.title.component parentComponentId:self.uut.bindedComponentId reactViewReadyBlock:[OCMArg any]];
169
+	[self.uut renderComponents:self.options perform:nil];
170
+	[(id)self.componentRegistry verify];
171
+	
172
+	
173
+	XCTAssertEqual(self.uut.bindedComponentId, @"componentId");
174
+}
175
+
176
+
177
+
178
+- (RNNLayoutInfo *)createLayoutInfoWithComponentId:(NSString *)componentId {
179
+	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] init];
180
+	layoutInfo.componentId = @"componentId";
181
+	return layoutInfo;
182
+}
135
 
183
 
136
 @end
184
 @end