Browse Source

Fix back button on iOS 13 (#5703)

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

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

@@ -28,9 +28,6 @@
28 28
 
29 29
 - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
30 30
 	[super applyOptionsOnWillMoveToParentViewController:options];
31
-	UIViewController* viewController = self.boundViewController;
32
-	RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
33
-	[viewController setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES] ? [withDefault.topBar.backButton.title getWithDefaultValue:nil] : @""];
34 31
 }
35 32
 
36 33
 - (void)applyOptions:(RNNNavigationOptions *)options {
@@ -158,12 +155,6 @@
158 155
 	}
159 156
 
160 157
 	[self setTitleViewWithSubtitle:withDefault];
161
-	
162
-	if (options.topBar.backButton.hasValue) {
163
-		UIViewController *lastViewControllerInStack = viewController.navigationController.viewControllers.count > 1 ? viewController.navigationController.viewControllers[viewController.navigationController.viewControllers.count - 2] : viewController.navigationController.topViewController;
164
-	    RNNNavigationOptions * resolvedOptions	= (RNNNavigationOptions *) [[currentOptions overrideOptions:options] withDefault:[self defaultOptions]];
165
-		[lastViewControllerInStack applyBackButton:resolvedOptions.topBar.backButton];
166
-	}
167 158
 }
168 159
 
169 160
 - (void)removeTitleComponentIfNeeded:(RNNNavigationOptions *)options {

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

@@ -44,6 +44,7 @@
44 44
 	[stack setNavigationBarLargeTitleFontFamily:[withDefault.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.largeTitle.fontSize getWithDefaultValue:nil] fontWeight:[withDefault.topBar.largeTitle.fontWeight getWithDefaultValue:nil] color:[withDefault.topBar.largeTitle.color getWithDefaultValue:nil]];
45 45
 	[stack setNavigationBarFontFamily:[withDefault.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.title.fontSize getWithDefaultValue:nil] fontWeight:[withDefault.topBar.title.fontWeight getWithDefaultValue:nil] color:[withDefault.topBar.title.color getWithDefaultValue:nil]];
46 46
 	[stack setBackButtonColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil]];
47
+    [stack setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.title getWithDefaultValue:nil] showTitle:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES]];
47 48
 }
48 49
 
49 50
 - (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options {
@@ -59,6 +60,7 @@
59 60
 	[navigationController setTopBarBackgroundColor:[withDefault.topBar.background.color getWithDefaultValue:nil]];
60 61
 	[navigationController setNavigationBarFontFamily:[withDefault.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.title.fontSize getWithDefaultValue:nil] fontWeight:[withDefault.topBar.title.fontWeight getWithDefaultValue:nil] color:[withDefault.topBar.title.color getWithDefaultValue:nil]];
61 62
 	[navigationController setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]];
63
+    [navigationController setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.title getWithDefaultValue:nil] showTitle:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES]];
62 64
 }
63 65
 
64 66
 - (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigationOptions *)resolvedOptions {
@@ -135,6 +137,10 @@
135 137
 	if (options.topBar.background.component.name.hasValue) {
136 138
 		[self setCustomNavigationComponentBackground:options perform:nil];
137 139
 	}
140
+    
141
+    if (options.topBar.backButton.hasValue) {
142
+        [stack setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.title getWithDefaultValue:nil] showTitle:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES]];
143
+    }
138 144
 }
139 145
 
140 146
 - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {

+ 2
- 0
lib/ios/UINavigationBar+utils.h View File

@@ -6,4 +6,6 @@
6 6
 
7 7
 - (void)rnn_setBackgroundColorTransparent;
8 8
 
9
+- (void)rnn_setBackIndicatorImage:(UIImage *)image;
10
+
9 11
 @end

+ 10
- 0
lib/ios/UINavigationBar+utils.m View File

@@ -57,6 +57,16 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
57 57
     }
58 58
 }
59 59
 
60
+- (void)rnn_setBackIndicatorImage:(UIImage *)image {
61
+    if (@available(iOS 13.0, *)) {
62
+        [[self getNavigaitonBarStandardAppearance] setBackIndicatorImage:image transitionMaskImage:image];
63
+        [[self getNavigaitonBarCompactAppearance] setBackIndicatorImage:image transitionMaskImage:image];
64
+        [[self getNavigaitonBarScrollEdgeAppearance] setBackIndicatorImage:image transitionMaskImage:image];
65
+    } else {
66
+        [self setBackIndicatorImage:image];
67
+        [self setBackIndicatorTransitionMaskImage:image];
68
+    }
69
+}
60 70
 
61 71
 - (UINavigationBarAppearance*)getNavigaitonBarStandardAppearance  API_AVAILABLE(ios(13.0)) {
62 72
     if (!self.standardAppearance) {

+ 2
- 0
lib/ios/UINavigationController+RNNOptions.h View File

@@ -30,4 +30,6 @@
30 30
 
31 31
 - (void)setBackButtonColor:(UIColor *)color;
32 32
 
33
+- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title showTitle:(BOOL)showTitle;
34
+
33 35
 @end

+ 22
- 0
lib/ios/UINavigationController+RNNOptions.m View File

@@ -1,5 +1,7 @@
1 1
 #import "UINavigationController+RNNOptions.h"
2 2
 #import "RNNFontAttributesCreator.h"
3
+#import "UIImage+tint.h"
4
+#import "UINavigationBar+utils.h"
3 5
 
4 6
 const NSInteger BLUR_TOPBAR_TAG = 78264802;
5 7
 
@@ -103,4 +105,24 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
103 105
 	self.navigationBar.clipsToBounds = clipsToBounds;
104 106
 }
105 107
 
108
+- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title showTitle:(BOOL)showTitle {
109
+    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
110
+    if (icon) {
111
+        icon = color
112
+        ? [[icon withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
113
+        : icon;
114
+    }
115
+    
116
+    [self.navigationBar rnn_setBackIndicatorImage:icon];
117
+
118
+    UIViewController *lastViewControllerInStack = self.viewControllers.count > 1 ? self.viewControllers[self.viewControllers.count - 2] : self.topViewController;
119
+
120
+    if (showTitle) {
121
+        backItem.title = title ? title : lastViewControllerInStack.navigationItem.title;
122
+    }
123
+    backItem.tintColor = color;
124
+
125
+    lastViewControllerInStack.navigationItem.backBarButtonItem = backItem;
126
+}
127
+
106 128
 @end

+ 0
- 2
lib/ios/UIViewController+RNNOptions.h View File

@@ -34,8 +34,6 @@
34 34
 
35 35
 - (void)setInterceptTouchOutside:(BOOL)interceptTouchOutside;
36 36
 
37
-- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title;
38
-
39 37
 - (void)applyBackButton:(RNNBackButtonOptions *)backButton;
40 38
 
41 39
 - (BOOL)isModal;

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

@@ -1,6 +1,7 @@
1 1
 #import "UIViewController+RNNOptions.h"
2 2
 #import <React/RCTRootView.h>
3 3
 #import "UIImage+tint.h"
4
+#import "UINavigationBar+utils.h"
4 5
 #import "RNNBottomTabOptions.h"
5 6
 #import "RNNNavigationOptions.h"
6 7
 #import "RNNBackButtonOptions.h"
@@ -160,25 +161,6 @@ const NSInteger BLUR_STATUS_TAG = 78264801;
160 161
 	}
161 162
 }
162 163
 
163
-- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title {
164
-	UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
165
-	if (icon) {
166
-		backItem.image = color
167
-		? [[icon withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
168
-		: icon;
169
-
170
-		[self.navigationController.navigationBar setBackIndicatorImage:[UIImage new]];
171
-		[self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage new]];
172
-	}
173
-
174
-	UIViewController *lastViewControllerInStack = self.navigationController.viewControllers.count > 1 ? self.navigationController.viewControllers[self.navigationController.viewControllers.count - 2] : self.navigationController.topViewController;
175
-
176
-	backItem.title = title ? title : lastViewControllerInStack.navigationItem.title;
177
-	backItem.tintColor = color;
178
-
179
-	lastViewControllerInStack.navigationItem.backBarButtonItem = backItem;
180
-}
181
-
182 164
 - (void)applyBackButton:(RNNBackButtonOptions *)backButton {
183 165
 	UIBarButtonItem *backItem = [UIBarButtonItem new];
184 166
 	if (backButton.icon.hasValue) {

+ 0
- 31
playground/ios/NavigationTests/RNNComponentPresenterTest.m View File

@@ -173,37 +173,6 @@
173 173
 	XCTAssertEqual(self.uut.boundComponentId, @"componentId");
174 174
 }
175 175
 
176
-- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withTitle {
177
-	Text* title = [[Text alloc] initWithValue:@"Title"];
178
-	self.options.topBar.backButton.title = title;
179
-	[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get];
180
-	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
181
-	[(id)self.boundViewController verify];
182
-}
183
-
184
-- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withHideTitle {
185
-	Text* title = [[Text alloc] initWithValue:@"Title"];
186
-	self.options.topBar.backButton.title = title;
187
-	self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)];
188
-	[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:@""];
189
-	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
190
-	[(id)self.boundViewController verify];
191
-}
192
-
193
-- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withIcon {
194
-	Image* image = [[Image alloc] initWithValue:[UIImage new]];
195
-	self.options.topBar.backButton.icon = image;
196
-	[[(id) self.boundViewController expect] setBackButtonIcon:image.get withColor:nil title:nil];
197
-	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
198
-	[(id)self.boundViewController verify];
199
-}
200
-
201
-- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withDefaultValues {
202
-	[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:nil];
203
-	[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
204
-	[(id)self.boundViewController verify];
205
-}
206
-
207 176
 - (void)testRemoveTitleComponentIfNeeded_componentIsRemovedIfTitleTextIsDefined {
208 177
 	id mockTitle = [OCMockObject niceMockForClass:[RNNReactView class]];
209 178
     OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any] reactViewReadyBlock:nil]).andReturn(mockTitle);

+ 31
- 0
playground/ios/NavigationTests/RNNStackPresenterTest.m View File

@@ -57,4 +57,35 @@
57 57
 	XCTAssertFalse([[self.uut.boundViewController navigationBar] prefersLargeTitles]);
58 58
 }
59 59
 
60
+- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withTitle {
61
+	Text* title = [[Text alloc] initWithValue:@"Title"];
62
+	self.options.topBar.backButton.title = title;
63
+	[[_boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get showTitle:YES];
64
+	[self.uut applyOptions:self.options];
65
+	[_boundViewController verify];
66
+}
67
+
68
+- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withHideTitle {
69
+	Text* title = [[Text alloc] initWithValue:@"Title"];
70
+	self.options.topBar.backButton.title = title;
71
+	self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)];
72
+	[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get showTitle:self.options.topBar.backButton.showTitle.get];
73
+	[self.uut applyOptions:self.options];
74
+	[(id)self.boundViewController verify];
75
+}
76
+
77
+- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withIcon {
78
+	Image* image = [[Image alloc] initWithValue:[UIImage new]];
79
+	self.options.topBar.backButton.icon = image;
80
+	[[(id) self.boundViewController expect] setBackButtonIcon:image.get withColor:nil title:nil showTitle:YES];
81
+	[self.uut applyOptions:self.options];
82
+	[(id)self.boundViewController verify];
83
+}
84
+
85
+- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withDefaultValues {
86
+	[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:nil showTitle:YES];
87
+	[self.uut applyOptions:self.options];
88
+	[(id)self.boundViewController verify];
89
+}
90
+
60 91
 @end

+ 38
- 0
playground/ios/NavigationTests/UINavigationController+RNNOptionsTest.m View File

@@ -11,4 +11,42 @@
11 11
     [super setUp];
12 12
 }
13 13
 
14
+- (void)testSetBackButtonIcon_withColor_shouldSetColor {
15
+	UIViewController* vc = [UIViewController new];
16
+	UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
17
+	UIColor* color = [UIColor blackColor];
18
+
19
+	[uut setBackButtonIcon:nil withColor:color title:nil showTitle:nil];
20
+	XCTAssertEqual(color, vc.navigationItem.backBarButtonItem.tintColor);
21
+}
22
+
23
+- (void)testSetBackButtonIcon_withColor_shouldSetTitle {
24
+	UIViewController* vc = [UIViewController new];
25
+	UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
26
+    NSString* title = @"Title";
27
+
28
+    [uut setBackButtonIcon:nil withColor:nil title:title showTitle:YES];
29
+	XCTAssertEqual(title, vc.navigationItem.backBarButtonItem.title);
30
+}
31
+
32
+//- (void)testSetBackButtonIcon_withColor_shouldSetIcon {
33
+//	UIViewController* vc = [UIViewController new];
34
+//	UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
35
+//    UIImage* icon = [UIImage new];
36
+//
37
+//    [uut setBackButtonIcon:icon withColor:nil title:nil showTitle:nil];
38
+//	XCTAssertEqual(icon, vc.navigationItem.backBarButtonItem.image);
39
+//}
40
+
41
+- (void)testSetBackButtonIcon_shouldSetTitleOnPreviousViewControllerIfExists {
42
+	UIViewController* viewController1 = [UIViewController new];
43
+	UIViewController* viewController2 = [UIViewController new];
44
+	UINavigationController* uut = [[UINavigationController alloc] init];
45
+	[uut setViewControllers:@[viewController1, viewController2]];
46
+	NSString* title = @"Title";
47
+
48
+	[uut setBackButtonIcon:nil withColor:nil title:title showTitle:YES];
49
+	XCTAssertEqual(title, viewController1.navigationItem.backBarButtonItem.title);
50
+}
51
+
14 52
 @end

+ 0
- 38
playground/ios/NavigationTests/UIViewController+LayoutProtocolTest.m View File

@@ -42,44 +42,6 @@
42 42
 	XCTAssertEqual(uut.viewControllers[1], child2);
43 43
 }
44 44
 
45
-- (void)testSetBackButtonIcon_withColor_shouldSetColor {
46
-	UIViewController* uut = [UIViewController new];
47
-	[[UINavigationController alloc] initWithRootViewController:uut];
48
-	UIColor* color = [UIColor blackColor];
49
-
50
-    [uut setBackButtonIcon:nil withColor:color title:nil];
51
-	XCTAssertEqual(color, uut.navigationItem.backBarButtonItem.tintColor);
52
-}
53
-
54
-- (void)testSetBackButtonIcon_withColor_shouldSetTitle {
55
-	UIViewController* uut = [UIViewController new];
56
-    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:uut];
57
-    NSString* title = @"Title";
58
-
59
-    [uut setBackButtonIcon:nil withColor:nil title:title];
60
-	XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title);
61
-}
62
-
63
-- (void)testSetBackButtonIcon_withColor_shouldSetIcon {
64
-	UIViewController* uut = [UIViewController new];
65
-    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:uut];
66
-    UIImage* icon = [UIImage new];
67
-
68
-    [uut setBackButtonIcon:icon withColor:nil title:nil];
69
-	XCTAssertEqual(icon, uut.navigationItem.backBarButtonItem.image);
70
-}
71
-
72
-- (void)testSetBackButtonIcon_shouldSetTitleOnPreviousViewControllerIfExists {
73
-	UIViewController* uut = [UIViewController new];
74
-	UIViewController* viewController2 = [UIViewController new];
75
-	UINavigationController* nav = [[UINavigationController alloc] init];
76
-	[nav setViewControllers:@[uut, viewController2]];
77
-	NSString* title = @"Title";
78
-
79
-    [uut setBackButtonIcon:nil withColor:nil title:title];
80
-	XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title);
81
-}
82
-
83 45
 - (void)testResolveOptions {
84 46
 	RNNComponentPresenter* presenter = [[RNNComponentPresenter alloc] init];
85 47