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,10 +39,12 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);
39 39
 
40 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 50
 @end

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

@@ -36,6 +36,13 @@
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 46
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions {
40 47
     UIViewController* viewController = self.boundViewController;
41 48
     RNNNavigationOptions *withDefault = [initialOptions withDefault:[self defaultOptions]];
@@ -78,8 +85,8 @@
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 90
     NSString* statusBarStyle = [withDefault.statusBar.style getWithDefaultValue:@"default"];
84 91
     if ([statusBarStyle isEqualToString:@"light"]) {
85 92
         return UIStatusBarStyleLightContent;
@@ -98,16 +105,16 @@
98 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 114
     if (withDefault.statusBar.visible.hasValue) {
108 115
         return ![withDefault.statusBar.visible get];
109 116
     } else if ([withDefault.statusBar.hideWithTopBar getWithDefaultValue:NO]) {
110
-        return stack.isNavigationBarHidden;
117
+        return self.boundViewController.stack.isNavigationBarHidden;
111 118
     }
112 119
     return NO;
113 120
 }

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

@@ -87,14 +87,6 @@
87 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 90
 #pragma mark UITabBarControllerDelegate
99 91
 
100 92
 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
@@ -121,4 +113,23 @@
121 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 135
 @end

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

@@ -6,7 +6,6 @@
6 6
 
7 7
 - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo rootViewCreator:(id<RNNComponentViewCreator>)creator eventEmitter:(RNNEventEmitter *)eventEmitter presenter:(RNNComponentPresenter *)presenter options:(RNNNavigationOptions *)options defaultOptions:(RNNNavigationOptions *)defaultOptions {
8 8
 	self = [super initWithLayoutInfo:layoutInfo creator:creator options:options defaultOptions:defaultOptions presenter:presenter eventEmitter:eventEmitter childViewControllers:nil];
9
-	self.extendedLayoutIncludesOpaqueBars = YES;
10 9
     if (@available(iOS 13.0, *)) {
11 10
         self.navigationItem.standardAppearance = [UINavigationBarAppearance new];
12 11
         self.navigationItem.scrollEdgeAppearance = [UINavigationBarAppearance new];
@@ -79,14 +78,6 @@
79 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 81
 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
91 82
 	return self.previewController;
92 83
 }
@@ -139,5 +130,23 @@
139 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 152
 @end

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

@@ -30,4 +30,22 @@
30 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 51
 @end

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

@@ -39,8 +39,22 @@
39 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 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 60
 @end

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

@@ -130,14 +130,6 @@
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 133
 - (UIViewController<RNNLayoutProtocol> *)getCurrentChild {
142 134
 	return self.openedViewController;
143 135
 }
@@ -163,4 +155,22 @@
163 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 176
 @end

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

@@ -9,12 +9,26 @@
9 9
     self.delegate = masterViewController;
10 10
 }
11 11
 
12
--(void)viewWillAppear:(BOOL)animated{
13
-	[super viewWillAppear:animated];
14
-}
15
-
16 12
 - (UIViewController *)getCurrentChild {
17 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 34
 @end

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

@@ -35,14 +35,6 @@
35 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 38
 - (UIViewController *)popViewControllerAnimated:(BOOL)animated {
47 39
     [self prepareForPop];
48 40
 	return [super popViewControllerAnimated:animated];
@@ -62,4 +54,22 @@
62 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 75
 @end

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

@@ -20,6 +20,7 @@
20 20
     self.eventEmitter = eventEmitter;
21 21
     self.presenter = presenter;
22 22
     [self.presenter bindViewController:self];
23
+    self.extendedLayoutIncludesOpaqueBars = YES;
23 24
     if ([self respondsToSelector:@selector(setViewControllers:)]) {
24 25
         [self performSelector:@selector(setViewControllers:) withObject:childViewControllers];
25 26
     }
@@ -51,15 +52,6 @@
51 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 55
 - (UINavigationController *)stack {
64 56
     if ([self isKindOfClass:UINavigationController.class]) {
65 57
         return (UINavigationController *)self;
@@ -161,13 +153,6 @@
161 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 156
 #pragma mark getters and setters to associated object
172 157
 
173 158
 - (RNNNavigationOptions *)options {

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

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

+ 10
- 14
playground/ios/NavigationTests/RNNBasePresenterTest.m View File

@@ -2,7 +2,7 @@
2 2
 #import "RNNBasePresenter.h"
3 3
 #import <OCMock/OCMock.h>
4 4
 #import "UIViewController+RNNOptions.h"
5
-#import "RNNComponentViewController.h"
5
+#import "RNNComponentViewController+Utils.h"
6 6
 
7 7
 @interface RNNBasePresenterTest : XCTestCase
8 8
 
@@ -18,7 +18,7 @@
18 18
 - (void)setUp {
19 19
     [super setUp];
20 20
     self.uut = [[RNNBasePresenter alloc] initWithDefaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions]];
21
-    self.boundViewController = [RNNComponentViewController new];
21
+    self.boundViewController = [RNNComponentViewController createWithComponentId:@"componentId" initialOptions:[RNNNavigationOptions emptyOptions]];
22 22
     self.mockBoundViewController = [OCMockObject partialMockForObject:self.boundViewController];
23 23
 	[self.uut bindViewController:self.mockBoundViewController];
24 24
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
@@ -53,32 +53,28 @@
53 53
 }
54 54
 
55 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 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 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 72
 - (void)testGetPreferredStatusBarStyle_considersDefaultOptions {
76
-    RNNNavigationOptions * options = [[RNNNavigationOptions alloc] initEmptyOptions];
77 73
     RNNNavigationOptions * lightOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
78 74
     lightOptions.statusBar.style = [[Text alloc] initWithValue:@"light"];
79 75
     [_uut setDefaultOptions:lightOptions];
80 76
 
81
-    XCTAssertEqual([_uut getStatusBarStyle:options], UIStatusBarStyleLightContent);
77
+    XCTAssertEqual([_uut getStatusBarStyle], UIStatusBarStyleLightContent);
82 78
 }
83 79
 
84 80
 - (void)testApplyOptionsOnInit_setSwipeToDismiss {

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

@@ -16,9 +16,12 @@
16 16
 - (void)setUp {
17 17
     [super setUp];
18 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 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