Skip to content

Commit

Permalink
Fix back button on iOS 13 (#5703)
Browse files Browse the repository at this point in the history
  • Loading branch information
yogevbd authored Dec 1, 2019
1 parent 7ccc9bf commit ed7c579
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 99 deletions.
9 changes: 0 additions & 9 deletions lib/ios/RNNComponentPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ - (void)boundViewController:(UIViewController *)boundViewController {

- (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
[super applyOptionsOnWillMoveToParentViewController:options];
UIViewController* viewController = self.boundViewController;
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
[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] : @""];
}

- (void)applyOptions:(RNNNavigationOptions *)options {
Expand Down Expand Up @@ -158,12 +155,6 @@ - (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigat
}

[self setTitleViewWithSubtitle:withDefault];

if (options.topBar.backButton.hasValue) {
UIViewController *lastViewControllerInStack = viewController.navigationController.viewControllers.count > 1 ? viewController.navigationController.viewControllers[viewController.navigationController.viewControllers.count - 2] : viewController.navigationController.topViewController;
RNNNavigationOptions * resolvedOptions = (RNNNavigationOptions *) [[currentOptions overrideOptions:options] withDefault:[self defaultOptions]];
[lastViewControllerInStack applyBackButton:resolvedOptions.topBar.backButton];
}
}

- (void)removeTitleComponentIfNeeded:(RNNNavigationOptions *)options {
Expand Down
6 changes: 6 additions & 0 deletions lib/ios/RNNStackPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ - (void)applyOptions:(RNNNavigationOptions *)options {
[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]];
[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]];
[stack setBackButtonColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil]];
[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]];
}

- (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options {
Expand All @@ -59,6 +60,7 @@ - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options {
[navigationController setTopBarBackgroundColor:[withDefault.topBar.background.color getWithDefaultValue:nil]];
[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]];
[navigationController setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]];
[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]];
}

- (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigationOptions *)resolvedOptions {
Expand Down Expand Up @@ -135,6 +137,10 @@ - (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigat
if (options.topBar.background.component.name.hasValue) {
[self setCustomNavigationComponentBackground:options perform:nil];
}

if (options.topBar.backButton.hasValue) {
[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]];
}
}

- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
Expand Down
2 changes: 2 additions & 0 deletions lib/ios/UINavigationBar+utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

- (void)rnn_setBackgroundColorTransparent;

- (void)rnn_setBackIndicatorImage:(UIImage *)image;

@end
10 changes: 10 additions & 0 deletions lib/ios/UINavigationBar+utils.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ - (void)removeTransparentView {
}
}

- (void)rnn_setBackIndicatorImage:(UIImage *)image {
if (@available(iOS 13.0, *)) {
[[self getNavigaitonBarStandardAppearance] setBackIndicatorImage:image transitionMaskImage:image];
[[self getNavigaitonBarCompactAppearance] setBackIndicatorImage:image transitionMaskImage:image];
[[self getNavigaitonBarScrollEdgeAppearance] setBackIndicatorImage:image transitionMaskImage:image];
} else {
[self setBackIndicatorImage:image];
[self setBackIndicatorTransitionMaskImage:image];
}
}

- (UINavigationBarAppearance*)getNavigaitonBarStandardAppearance API_AVAILABLE(ios(13.0)) {
if (!self.standardAppearance) {
Expand Down
2 changes: 2 additions & 0 deletions lib/ios/UINavigationController+RNNOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@

- (void)setBackButtonColor:(UIColor *)color;

- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title showTitle:(BOOL)showTitle;

@end
22 changes: 22 additions & 0 deletions lib/ios/UINavigationController+RNNOptions.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#import "UINavigationController+RNNOptions.h"
#import "RNNFontAttributesCreator.h"
#import "UIImage+tint.h"
#import "UINavigationBar+utils.h"

const NSInteger BLUR_TOPBAR_TAG = 78264802;

Expand Down Expand Up @@ -103,4 +105,24 @@ - (void)setNavigationBarClipsToBounds:(BOOL)clipsToBounds {
self.navigationBar.clipsToBounds = clipsToBounds;
}

- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title showTitle:(BOOL)showTitle {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
if (icon) {
icon = color
? [[icon withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
: icon;
}

[self.navigationBar rnn_setBackIndicatorImage:icon];

UIViewController *lastViewControllerInStack = self.viewControllers.count > 1 ? self.viewControllers[self.viewControllers.count - 2] : self.topViewController;

if (showTitle) {
backItem.title = title ? title : lastViewControllerInStack.navigationItem.title;
}
backItem.tintColor = color;

lastViewControllerInStack.navigationItem.backBarButtonItem = backItem;
}

@end
2 changes: 0 additions & 2 deletions lib/ios/UIViewController+RNNOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@

- (void)setInterceptTouchOutside:(BOOL)interceptTouchOutside;

- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title;

- (void)applyBackButton:(RNNBackButtonOptions *)backButton;

- (BOOL)isModal;
Expand Down
20 changes: 1 addition & 19 deletions lib/ios/UIViewController+RNNOptions.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "UIViewController+RNNOptions.h"
#import <React/RCTRootView.h>
#import "UIImage+tint.h"
#import "UINavigationBar+utils.h"
#import "RNNBottomTabOptions.h"
#import "RNNNavigationOptions.h"
#import "RNNBackButtonOptions.h"
Expand Down Expand Up @@ -160,25 +161,6 @@ - (void)setInterceptTouchOutside:(BOOL)interceptTouchOutside {
}
}

- (void)setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
if (icon) {
backItem.image = color
? [[icon withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
: icon;

[self.navigationController.navigationBar setBackIndicatorImage:[UIImage new]];
[self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage new]];
}

UIViewController *lastViewControllerInStack = self.navigationController.viewControllers.count > 1 ? self.navigationController.viewControllers[self.navigationController.viewControllers.count - 2] : self.navigationController.topViewController;

backItem.title = title ? title : lastViewControllerInStack.navigationItem.title;
backItem.tintColor = color;

lastViewControllerInStack.navigationItem.backBarButtonItem = backItem;
}

- (void)applyBackButton:(RNNBackButtonOptions *)backButton {
UIBarButtonItem *backItem = [UIBarButtonItem new];
if (backButton.icon.hasValue) {
Expand Down
31 changes: 0 additions & 31 deletions playground/ios/NavigationTests/RNNComponentPresenterTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -173,37 +173,6 @@ - (void)testRenderComponentsCreateReactViewWithBoundComponentId {
XCTAssertEqual(self.uut.boundComponentId, @"componentId");
}

- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withTitle {
Text* title = [[Text alloc] initWithValue:@"Title"];
self.options.topBar.backButton.title = title;
[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get];
[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
[(id)self.boundViewController verify];
}

- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withHideTitle {
Text* title = [[Text alloc] initWithValue:@"Title"];
self.options.topBar.backButton.title = title;
self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)];
[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:@""];
[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
[(id)self.boundViewController verify];
}

- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withIcon {
Image* image = [[Image alloc] initWithValue:[UIImage new]];
self.options.topBar.backButton.icon = image;
[[(id) self.boundViewController expect] setBackButtonIcon:image.get withColor:nil title:nil];
[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
[(id)self.boundViewController verify];
}

- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBoundViewController_withDefaultValues {
[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:nil];
[self.uut applyOptionsOnWillMoveToParentViewController:self.options];
[(id)self.boundViewController verify];
}

- (void)testRemoveTitleComponentIfNeeded_componentIsRemovedIfTitleTextIsDefined {
id mockTitle = [OCMockObject niceMockForClass:[RNNReactView class]];
OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any] reactViewReadyBlock:nil]).andReturn(mockTitle);
Expand Down
31 changes: 31 additions & 0 deletions playground/ios/NavigationTests/RNNStackPresenterTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,35 @@ - (void)testApplyOptionsBeforePoppingShouldSetDefaultLargeTitleFalseForPoppingVi
XCTAssertFalse([[self.uut.boundViewController navigationBar] prefersLargeTitles]);
}

- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withTitle {
Text* title = [[Text alloc] initWithValue:@"Title"];
self.options.topBar.backButton.title = title;
[[_boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get showTitle:YES];
[self.uut applyOptions:self.options];
[_boundViewController verify];
}

- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withHideTitle {
Text* title = [[Text alloc] initWithValue:@"Title"];
self.options.topBar.backButton.title = title;
self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)];
[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:title.get showTitle:self.options.topBar.backButton.showTitle.get];
[self.uut applyOptions:self.options];
[(id)self.boundViewController verify];
}

- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withIcon {
Image* image = [[Image alloc] initWithValue:[UIImage new]];
self.options.topBar.backButton.icon = image;
[[(id) self.boundViewController expect] setBackButtonIcon:image.get withColor:nil title:nil showTitle:YES];
[self.uut applyOptions:self.options];
[(id)self.boundViewController verify];
}

- (void)testApplyOptions_shouldSetBackButtonOnBoundViewController_withDefaultValues {
[[(id) self.boundViewController expect] setBackButtonIcon:nil withColor:nil title:nil showTitle:YES];
[self.uut applyOptions:self.options];
[(id)self.boundViewController verify];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,42 @@ - (void)setUp {
[super setUp];
}

- (void)testSetBackButtonIcon_withColor_shouldSetColor {
UIViewController* vc = [UIViewController new];
UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
UIColor* color = [UIColor blackColor];

[uut setBackButtonIcon:nil withColor:color title:nil showTitle:nil];
XCTAssertEqual(color, vc.navigationItem.backBarButtonItem.tintColor);
}

- (void)testSetBackButtonIcon_withColor_shouldSetTitle {
UIViewController* vc = [UIViewController new];
UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
NSString* title = @"Title";

[uut setBackButtonIcon:nil withColor:nil title:title showTitle:YES];
XCTAssertEqual(title, vc.navigationItem.backBarButtonItem.title);
}

//- (void)testSetBackButtonIcon_withColor_shouldSetIcon {
// UIViewController* vc = [UIViewController new];
// UINavigationController* uut = [[UINavigationController alloc] initWithRootViewController:vc];
// UIImage* icon = [UIImage new];
//
// [uut setBackButtonIcon:icon withColor:nil title:nil showTitle:nil];
// XCTAssertEqual(icon, vc.navigationItem.backBarButtonItem.image);
//}

- (void)testSetBackButtonIcon_shouldSetTitleOnPreviousViewControllerIfExists {
UIViewController* viewController1 = [UIViewController new];
UIViewController* viewController2 = [UIViewController new];
UINavigationController* uut = [[UINavigationController alloc] init];
[uut setViewControllers:@[viewController1, viewController2]];
NSString* title = @"Title";

[uut setBackButtonIcon:nil withColor:nil title:title showTitle:YES];
XCTAssertEqual(title, viewController1.navigationItem.backBarButtonItem.title);
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -42,44 +42,6 @@ - (void)testInitWithLayoutInfoShouldSetChildViewControllers {
XCTAssertEqual(uut.viewControllers[1], child2);
}

- (void)testSetBackButtonIcon_withColor_shouldSetColor {
UIViewController* uut = [UIViewController new];
[[UINavigationController alloc] initWithRootViewController:uut];
UIColor* color = [UIColor blackColor];

[uut setBackButtonIcon:nil withColor:color title:nil];
XCTAssertEqual(color, uut.navigationItem.backBarButtonItem.tintColor);
}

- (void)testSetBackButtonIcon_withColor_shouldSetTitle {
UIViewController* uut = [UIViewController new];
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:uut];
NSString* title = @"Title";

[uut setBackButtonIcon:nil withColor:nil title:title];
XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title);
}

- (void)testSetBackButtonIcon_withColor_shouldSetIcon {
UIViewController* uut = [UIViewController new];
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:uut];
UIImage* icon = [UIImage new];

[uut setBackButtonIcon:icon withColor:nil title:nil];
XCTAssertEqual(icon, uut.navigationItem.backBarButtonItem.image);
}

- (void)testSetBackButtonIcon_shouldSetTitleOnPreviousViewControllerIfExists {
UIViewController* uut = [UIViewController new];
UIViewController* viewController2 = [UIViewController new];
UINavigationController* nav = [[UINavigationController alloc] init];
[nav setViewControllers:@[uut, viewController2]];
NSString* title = @"Title";

[uut setBackButtonIcon:nil withColor:nil title:title];
XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title);
}

- (void)testResolveOptions {
RNNComponentPresenter* presenter = [[RNNComponentPresenter alloc] init];

Expand Down

0 comments on commit ed7c579

Please sign in to comment.