Browse Source

Fix styling options on iOS 13.4 (#6087)

iOS 13.4 doesn't allow overriding UIViewController's methods in categories (and it's also discouraged by apple) which causes styles to break.

Move UIViewController override methods from category to controllers.
Fixes BottomTab style visibility
Fixes statusBar.style
Closes #6075
Yogev Ben David 4 years ago
parent
commit
950ac6404f
No account linked to committer's email address

+ 5
- 3
lib/ios/RNNBasePresenter.h View File

39
 
39
 
40
 - (UINavigationItem *)currentNavigationItem;
40
 - (UINavigationItem *)currentNavigationItem;
41
 
41
 
42
-- (UIStatusBarStyle)getStatusBarStyle:(RNNNavigationOptions *)resolvedOptions;
42
+- (void)willMoveToParentViewController:(UIViewController *)parent;
43
 
43
 
44
-- (UIInterfaceOrientationMask)getOrientation:(RNNNavigationOptions *)options;
44
+- (UIStatusBarStyle)getStatusBarStyle;
45
 
45
 
46
-- (BOOL)statusBarVisibile:(UINavigationController *)stack resolvedOptions:(RNNNavigationOptions *)resolvedOptions;
46
+- (UIInterfaceOrientationMask)getOrientation;
47
+
48
+- (BOOL)getStatusBarVisibility;
47
 
49
 
48
 @end
50
 @end

+ 14
- 7
lib/ios/RNNBasePresenter.m View File

36
     
36
     
37
 }
37
 }
38
 
38
 
39
+- (void)willMoveToParentViewController:(UIViewController *)parent {
40
+    if (parent) {
41
+        [self applyOptionsOnWillMoveToParentViewController:self.boundViewController.resolveOptions];
42
+        [self.boundViewController onChildAddToParent:self.boundViewController options:self.boundViewController.resolveOptions];
43
+    }
44
+}
45
+
39
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions {
46
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions {
40
     UIViewController* viewController = self.boundViewController;
47
     UIViewController* viewController = self.boundViewController;
41
     RNNNavigationOptions *withDefault = [initialOptions withDefault:[self defaultOptions]];
48
     RNNNavigationOptions *withDefault = [initialOptions withDefault:[self defaultOptions]];
78
 
85
 
79
 }
86
 }
80
 
87
 
81
-- (UIStatusBarStyle)getStatusBarStyle:(RNNNavigationOptions *)resolvedOptions {
82
-    RNNNavigationOptions *withDefault = [resolvedOptions withDefault:[self defaultOptions]];
88
+- (UIStatusBarStyle)getStatusBarStyle {
89
+    RNNNavigationOptions *withDefault = [self.boundViewController.resolveOptions withDefault:[self defaultOptions]];
83
     NSString* statusBarStyle = [withDefault.statusBar.style getWithDefaultValue:@"default"];
90
     NSString* statusBarStyle = [withDefault.statusBar.style getWithDefaultValue:@"default"];
84
     if ([statusBarStyle isEqualToString:@"light"]) {
91
     if ([statusBarStyle isEqualToString:@"light"]) {
85
         return UIStatusBarStyleLightContent;
92
         return UIStatusBarStyleLightContent;
98
     return self.boundViewController.getCurrentChild.navigationItem;
105
     return self.boundViewController.getCurrentChild.navigationItem;
99
 }
106
 }
100
 
107
 
101
-- (UIInterfaceOrientationMask)getOrientation:(RNNNavigationOptions *)options {
102
-    return [options withDefault:[self defaultOptions]].layout.supportedOrientations;
108
+- (UIInterfaceOrientationMask)getOrientation {
109
+    return [self.boundViewController.resolveOptions withDefault:self.defaultOptions].layout.supportedOrientations;
103
 }
110
 }
104
 
111
 
105
-- (BOOL)statusBarVisibile:(UINavigationController *)stack resolvedOptions:(RNNNavigationOptions *)resolvedOptions {
106
-    RNNNavigationOptions *withDefault = [resolvedOptions withDefault:self.defaultOptions];
112
+- (BOOL)getStatusBarVisibility {
113
+    RNNNavigationOptions *withDefault = [self.boundViewController.resolveOptions withDefault:self.defaultOptions];
107
     if (withDefault.statusBar.visible.hasValue) {
114
     if (withDefault.statusBar.visible.hasValue) {
108
         return ![withDefault.statusBar.visible get];
115
         return ![withDefault.statusBar.visible get];
109
     } else if ([withDefault.statusBar.hideWithTopBar getWithDefaultValue:NO]) {
116
     } else if ([withDefault.statusBar.hideWithTopBar getWithDefaultValue:NO]) {
110
-        return stack.isNavigationBarHidden;
117
+        return self.boundViewController.stack.isNavigationBarHidden;
111
     }
118
     }
112
     return NO;
119
     return NO;
113
 }
120
 }

+ 19
- 8
lib/ios/RNNBottomTabsController.m View File

87
 	[super setSelectedIndex:selectedIndex];
87
 	[super setSelectedIndex:selectedIndex];
88
 }
88
 }
89
 
89
 
90
-- (UIStatusBarStyle)preferredStatusBarStyle {
91
-	return [[self presenter] getStatusBarStyle:self.resolveOptions];
92
-}
93
-
94
-- (BOOL)prefersStatusBarHidden {
95
-    return [self.presenter statusBarVisibile:self.navigationController resolvedOptions:self.resolveOptions];
96
-}
97
-
98
 #pragma mark UITabBarControllerDelegate
90
 #pragma mark UITabBarControllerDelegate
99
 
91
 
100
 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
92
 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
121
     return NO;
113
     return NO;
122
 }
114
 }
123
 
115
 
116
+# pragma mark - UIViewController overrides
117
+
118
+- (void)willMoveToParentViewController:(UIViewController *)parent {
119
+    [self.presenter willMoveToParentViewController:parent];
120
+}
121
+
122
+- (UIStatusBarStyle)preferredStatusBarStyle {
123
+    return [self.presenter getStatusBarStyle];
124
+}
125
+
126
+- (BOOL)prefersStatusBarHidden {
127
+    return [self.presenter getStatusBarVisibility];
128
+}
129
+
130
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
131
+    return [self.presenter getOrientation];
132
+}
133
+
134
+
124
 @end
135
 @end

+ 18
- 9
lib/ios/RNNComponentViewController.m View File

6
 
6
 
7
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo rootViewCreator:(id<RNNComponentViewCreator>)creator eventEmitter:(RNNEventEmitter *)eventEmitter presenter:(RNNComponentPresenter *)presenter options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions {
7
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo rootViewCreator:(id<RNNComponentViewCreator>)creator eventEmitter:(RNNEventEmitter *)eventEmitter presenter:(RNNComponentPresenter *)presenter options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions {
8
 	self = [super initWithLayoutInfo:layoutInfo creator:creator options:options defaultOptions:defaultOptions presenter:presenter eventEmitter:eventEmitter childViewControllers:nil];
8
 	self = [super initWithLayoutInfo:layoutInfo creator:creator options:options defaultOptions:defaultOptions presenter:presenter eventEmitter:eventEmitter childViewControllers:nil];
9
-	self.extendedLayoutIncludesOpaqueBars = YES;
10
     if (@available(iOS 13.0, *)) {
9
     if (@available(iOS 13.0, *)) {
11
         self.navigationItem.standardAppearance = [UINavigationBarAppearance new];
10
         self.navigationItem.standardAppearance = [UINavigationBarAppearance new];
12
         self.navigationItem.scrollEdgeAppearance = [UINavigationBarAppearance new];
11
         self.navigationItem.scrollEdgeAppearance = [UINavigationBarAppearance new];
79
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
78
 	[self.eventEmitter sendOnSearchBarCancelPressed:self.layoutInfo.componentId];
80
 }
79
 }
81
 
80
 
82
-- (UIStatusBarStyle)preferredStatusBarStyle {
83
-	return [_presenter getStatusBarStyle:[self resolveOptions]];
84
-}
85
-
86
-- (BOOL)prefersStatusBarHidden {
87
-    return [self.presenter statusBarVisibile:self.navigationController resolvedOptions:self.resolveOptions];
88
-}
89
-
90
 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
81
 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
91
 	return self.previewController;
82
 	return self.previewController;
92
 }
83
 }
139
 	[self.eventEmitter sendOnNavigationButtonPressed:self.layoutInfo.componentId buttonId:barButtonItem.buttonId];
130
 	[self.eventEmitter sendOnNavigationButtonPressed:self.layoutInfo.componentId buttonId:barButtonItem.buttonId];
140
 }
131
 }
141
 
132
 
133
+# pragma mark - UIViewController overrides
134
+
135
+- (void)willMoveToParentViewController:(UIViewController *)parent {
136
+    [self.presenter willMoveToParentViewController:parent];
137
+}
138
+
139
+- (UIStatusBarStyle)preferredStatusBarStyle {
140
+    return [self.presenter getStatusBarStyle];
141
+}
142
+
143
+- (BOOL)prefersStatusBarHidden {
144
+    return [self.presenter getStatusBarVisibility];
145
+}
146
+
147
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
148
+    return [self.presenter getOrientation];
149
+}
150
+
142
 
151
 
143
 @end
152
 @end

+ 18
- 0
lib/ios/RNNExternalViewController.m View File

30
 	[self readyForPresentation];
30
 	[self readyForPresentation];
31
 }
31
 }
32
 
32
 
33
+# pragma mark - UIViewController overrides
34
+
35
+- (void)willMoveToParentViewController:(UIViewController *)parent {
36
+    [self.presenter willMoveToParentViewController:parent];
37
+}
38
+
39
+- (UIStatusBarStyle)preferredStatusBarStyle {
40
+    return [self.presenter getStatusBarStyle];
41
+}
42
+
43
+- (BOOL)prefersStatusBarHidden {
44
+    return [self.presenter getStatusBarVisibility];
45
+}
46
+
47
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
48
+    return [self.presenter getOrientation];
49
+}
50
+
33
 @end
51
 @end

+ 15
- 1
lib/ios/RNNSideMenuChildVC.m View File

39
 	return self.child;
39
 	return self.child;
40
 }
40
 }
41
 
41
 
42
+# pragma mark - UIViewController overrides
43
+
44
+- (void)willMoveToParentViewController:(UIViewController *)parent {
45
+    [self.presenter willMoveToParentViewController:parent];
46
+}
47
+
42
 - (UIStatusBarStyle)preferredStatusBarStyle {
48
 - (UIStatusBarStyle)preferredStatusBarStyle {
43
-	return [[self presenter] getStatusBarStyle:[self resolveOptions]];
49
+    return [self.presenter getStatusBarStyle];
50
+}
51
+
52
+- (BOOL)prefersStatusBarHidden {
53
+    return [self.presenter getStatusBarVisibility];
54
+}
55
+
56
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
57
+    return [self.presenter getOrientation];
44
 }
58
 }
45
 
59
 
46
 @end
60
 @end

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

130
 	}
130
 	}
131
 }
131
 }
132
 
132
 
133
-- (UIStatusBarStyle)preferredStatusBarStyle {
134
-	return self.openedViewController.preferredStatusBarStyle;
135
-}
136
-
137
-- (BOOL)prefersStatusBarHidden {
138
-    return [self.presenter statusBarVisibile:self.navigationController resolvedOptions:self.resolveOptions];
139
-}
140
-
141
 - (UIViewController<RNNLayoutProtocol> *)getCurrentChild {
133
 - (UIViewController<RNNLayoutProtocol> *)getCurrentChild {
142
 	return self.openedViewController;
134
 	return self.openedViewController;
143
 }
135
 }
163
     return options;
155
     return options;
164
 }
156
 }
165
 
157
 
158
+# pragma mark - UIViewController overrides
159
+
160
+- (void)willMoveToParentViewController:(UIViewController *)parent {
161
+    [self.presenter willMoveToParentViewController:parent];
162
+}
163
+
164
+- (UIStatusBarStyle)preferredStatusBarStyle {
165
+    return [self.presenter getStatusBarStyle];
166
+}
167
+
168
+- (BOOL)prefersStatusBarHidden {
169
+    return [self.presenter getStatusBarVisibility];
170
+}
171
+
172
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
173
+    return [self.presenter getOrientation];
174
+}
175
+
166
 @end
176
 @end

+ 18
- 4
lib/ios/RNNSplitViewController.m View File

9
     self.delegate = masterViewController;
9
     self.delegate = masterViewController;
10
 }
10
 }
11
 
11
 
12
--(void)viewWillAppear:(BOOL)animated{
13
-	[super viewWillAppear:animated];
14
-}
15
-
16
 - (UIViewController *)getCurrentChild {
12
 - (UIViewController *)getCurrentChild {
17
 	return self.viewControllers[0];
13
 	return self.viewControllers[0];
18
 }
14
 }
19
 
15
 
16
+# pragma mark - UIViewController overrides
17
+
18
+- (void)willMoveToParentViewController:(UIViewController *)parent {
19
+    [self.presenter willMoveToParentViewController:parent];
20
+}
21
+
22
+- (UIStatusBarStyle)preferredStatusBarStyle {
23
+    return [self.presenter getStatusBarStyle];
24
+}
25
+
26
+- (BOOL)prefersStatusBarHidden {
27
+    return [self.presenter getStatusBarVisibility];
28
+}
29
+
30
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
31
+    return [self.presenter getOrientation];
32
+}
33
+
20
 @end
34
 @end

+ 18
- 8
lib/ios/RNNStackController.m View File

35
     [self.parentViewController mergeChildOptions:options child:child];
35
     [self.parentViewController mergeChildOptions:options child:child];
36
 }
36
 }
37
 
37
 
38
-- (UIStatusBarStyle)preferredStatusBarStyle {
39
-	return [_presenter getStatusBarStyle:self.resolveOptions];
40
-}
41
-
42
-- (BOOL)prefersStatusBarHidden {
43
-    return [self.presenter statusBarVisibile:self.navigationController resolvedOptions:self.resolveOptions];
44
-}
45
-
46
 - (UIViewController *)popViewControllerAnimated:(BOOL)animated {
38
 - (UIViewController *)popViewControllerAnimated:(BOOL)animated {
47
     [self prepareForPop];
39
     [self prepareForPop];
48
 	return [super popViewControllerAnimated:animated];
40
 	return [super popViewControllerAnimated:animated];
62
 	return self.topViewController;
54
 	return self.topViewController;
63
 }
55
 }
64
 
56
 
57
+# pragma mark - UIViewController overrides
58
+
59
+- (void)willMoveToParentViewController:(UIViewController *)parent {
60
+    [self.presenter willMoveToParentViewController:parent];
61
+}
62
+
63
+- (UIStatusBarStyle)preferredStatusBarStyle {
64
+    return [self.presenter getStatusBarStyle];
65
+}
66
+
67
+- (BOOL)prefersStatusBarHidden {
68
+    return [self.presenter getStatusBarVisibility];
69
+}
70
+
71
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
72
+    return [self.presenter getOrientation];
73
+}
74
+
65
 @end
75
 @end

+ 1
- 16
lib/ios/UIViewController+LayoutProtocol.m View File

20
     self.eventEmitter = eventEmitter;
20
     self.eventEmitter = eventEmitter;
21
     self.presenter = presenter;
21
     self.presenter = presenter;
22
     [self.presenter bindViewController:self];
22
     [self.presenter bindViewController:self];
23
+    self.extendedLayoutIncludesOpaqueBars = YES;
23
     if ([self respondsToSelector:@selector(setViewControllers:)]) {
24
     if ([self respondsToSelector:@selector(setViewControllers:)]) {
24
         [self performSelector:@selector(setViewControllers:) withObject:childViewControllers];
25
         [self performSelector:@selector(setViewControllers:) withObject:childViewControllers];
25
     }
26
     }
51
 	[self.options overrideOptions:options];
52
 	[self.options overrideOptions:options];
52
 }
53
 }
53
 
54
 
54
-- (BOOL)extendedLayoutIncludesOpaqueBars {
55
-    return YES;
56
-}
57
-
58
-- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
59
-	UIInterfaceOrientationMask interfaceOrientationMask = self.presenter ? [self.presenter getOrientation:[self resolveOptions]] : [[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:[[UIApplication sharedApplication] keyWindow]];
60
-	return interfaceOrientationMask;
61
-}
62
-
63
 - (UINavigationController *)stack {
55
 - (UINavigationController *)stack {
64
     if ([self isKindOfClass:UINavigationController.class]) {
56
     if ([self isKindOfClass:UINavigationController.class]) {
65
         return (UINavigationController *)self;
57
         return (UINavigationController *)self;
161
     [self.parentViewController componentDidDisappear];
153
     [self.parentViewController componentDidDisappear];
162
 }
154
 }
163
 
155
 
164
-- (void)willMoveToParentViewController:(UIViewController *)parent {
165
-	if (parent) {
166
-		[self.presenter applyOptionsOnWillMoveToParentViewController:self.resolveOptions];
167
-        [self onChildAddToParent:self options:self.resolveOptions];
168
-	}
169
-}
170
-
171
 #pragma mark getters and setters to associated object
156
 #pragma mark getters and setters to associated object
172
 
157
 
173
 - (RNNNavigationOptions *)options {
158
 - (RNNNavigationOptions *)options {

+ 1
- 1
playground/ios/NavigationTests/BottomTabsControllerTest.m View File

139
 }
139
 }
140
 
140
 
141
 - (void)testPreferredStatusBarStyle_shouldInvokeSelectedViewControllerPreferredStatusBarStyle {
141
 - (void)testPreferredStatusBarStyle_shouldInvokeSelectedViewControllerPreferredStatusBarStyle {
142
-    [[self.mockTabBarPresenter expect] getStatusBarStyle:[OCMArg any]];
142
+    [[self.mockTabBarPresenter expect] getStatusBarStyle];
143
     [self.uut preferredStatusBarStyle];
143
     [self.uut preferredStatusBarStyle];
144
     [self.mockTabBarPresenter verify];
144
     [self.mockTabBarPresenter verify];
145
 }
145
 }

+ 10
- 14
playground/ios/NavigationTests/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 "RNNComponentViewController.h"
5
+#import "RNNComponentViewController+Utils.h"
6
 
6
 
7
 @interface RNNBasePresenterTest : XCTestCase
7
 @interface RNNBasePresenterTest : XCTestCase
8
 
8
 
18
 - (void)setUp {
18
 - (void)setUp {
19
     [super setUp];
19
     [super setUp];
20
     self.uut = [[RNNBasePresenter alloc] initWithDefaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
20
     self.uut = [[RNNBasePresenter alloc] initWithDefaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
21
-    self.boundViewController = [RNNComponentViewController new];
21
+    self.boundViewController = [RNNComponentViewController createWithComponentId:@"componentId" initialOptions:[RNNNavigationOptions emptyOptions]];
22
     self.mockBoundViewController = [OCMockObject partialMockForObject:self.boundViewController];
22
     self.mockBoundViewController = [OCMockObject partialMockForObject:self.boundViewController];
23
 	[self.uut bindViewController:self.mockBoundViewController];
23
 	[self.uut bindViewController:self.mockBoundViewController];
24
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
24
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
53
 }
53
 }
54
 
54
 
55
 - (void)testGetPreferredStatusBarStyle_returnLightIfLight {
55
 - (void)testGetPreferredStatusBarStyle_returnLightIfLight {
56
-    RNNNavigationOptions * lightOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
57
-    lightOptions.statusBar.style = [[Text alloc] initWithValue:@"light"];
58
-
59
-    XCTAssertEqual([_uut getStatusBarStyle:lightOptions], UIStatusBarStyleLightContent);
56
+	self.boundViewController.options.statusBar.style = [[Text alloc] initWithValue:@"light"];
57
+	
58
+    XCTAssertEqual([_uut getStatusBarStyle], UIStatusBarStyleLightContent);
60
 }
59
 }
61
 
60
 
62
 - (void)testGetPreferredStatusBarStyle_returnDark {
61
 - (void)testGetPreferredStatusBarStyle_returnDark {
63
-    RNNNavigationOptions * darkOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
64
-    darkOptions.statusBar.style = [[Text alloc] initWithValue:@"dark"];
62
+    self.boundViewController.options.statusBar.style = [[Text alloc] initWithValue:@"dark"];
65
 
63
 
66
-    XCTAssertEqual([_uut getStatusBarStyle:darkOptions], UIStatusBarStyleDarkContent);
64
+    XCTAssertEqual([_uut getStatusBarStyle], UIStatusBarStyleDarkContent);
67
 }
65
 }
68
 
66
 
69
 - (void)testGetPreferredStatusBarStyle_returnDefaultIfNil {
67
 - (void)testGetPreferredStatusBarStyle_returnDefaultIfNil {
70
-    RNNNavigationOptions * options = [[RNNNavigationOptions alloc] initEmptyOptions];
71
-
72
-    XCTAssertEqual([_uut getStatusBarStyle:options], UIStatusBarStyleDefault);
68
+	self.boundViewController.options.statusBar.style = nil;
69
+    XCTAssertEqual([_uut getStatusBarStyle], UIStatusBarStyleDefault);
73
 }
70
 }
74
 
71
 
75
 - (void)testGetPreferredStatusBarStyle_considersDefaultOptions {
72
 - (void)testGetPreferredStatusBarStyle_considersDefaultOptions {
76
-    RNNNavigationOptions * options = [[RNNNavigationOptions alloc] initEmptyOptions];
77
     RNNNavigationOptions * lightOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
73
     RNNNavigationOptions * lightOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
78
     lightOptions.statusBar.style = [[Text alloc] initWithValue:@"light"];
74
     lightOptions.statusBar.style = [[Text alloc] initWithValue:@"light"];
79
     [_uut setDefaultOptions:lightOptions];
75
     [_uut setDefaultOptions:lightOptions];
80
 
76
 
81
-    XCTAssertEqual([_uut getStatusBarStyle:options], UIStatusBarStyleLightContent);
77
+    XCTAssertEqual([_uut getStatusBarStyle], UIStatusBarStyleLightContent);
82
 }
78
 }
83
 
79
 
84
 - (void)testApplyOptionsOnInit_setSwipeToDismiss {
80
 - (void)testApplyOptionsOnInit_setSwipeToDismiss {

+ 6
- 3
playground/ios/NavigationTests/RNNSideMenuControllerTest.m View File

16
 - (void)setUp {
16
 - (void)setUp {
17
     [super setUp];
17
     [super setUp];
18
 	_creator = [[RNNTestRootViewCreator alloc] init];
18
 	_creator = [[RNNTestRootViewCreator alloc] init];
19
-	_leftVC = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:nil eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeLeft];
20
-	_rightVC = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:nil eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeRight];
21
-	_centerVC =[[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:nil eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeCenter];
19
+	_leftVC = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:[RNNBasePresenter new] eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeLeft];
20
+	[_leftVC.presenter bindViewController:_leftVC];
21
+	_rightVC = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:[RNNBasePresenter new] eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeRight];
22
+	[_rightVC.presenter bindViewController:_rightVC];
23
+	_centerVC =[[RNNSideMenuChildVC alloc] initWithLayoutInfo:nil creator:nil options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:[RNNBasePresenter new] eventEmitter:nil childViewController:self.generateComponent type:RNNSideMenuChildTypeCenter];
24
+	[_centerVC.presenter bindViewController:_centerVC];
22
 	self.uut = [[RNNSideMenuController alloc] initWithLayoutInfo:nil creator:nil childViewControllers:@[_leftVC, _centerVC, _rightVC] options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:[[RNNSideMenuPresenter alloc] initWithDefaultOptions:nil] eventEmitter:nil];
25
 	self.uut = [[RNNSideMenuController alloc] initWithLayoutInfo:nil creator:nil childViewControllers:@[_leftVC, _centerVC, _rightVC] options:[RNNNavigationOptions emptyOptions] defaultOptions:nil presenter:[[RNNSideMenuPresenter alloc] initWithDefaultOptions:nil] eventEmitter:nil];
23
 }
26
 }
24
 
27