From c0ad1945a3dbbc29192abdcc1c598516b391a10f Mon Sep 17 00:00:00 2001 From: Yogev Ben David Date: Mon, 1 Jul 2019 18:10:55 +0300 Subject: [PATCH] Fix back button initialization on setStackRoot (#5246) --- lib/ios/RNNNavigationControllerPresenter.m | 9 --- lib/ios/RNNViewControllerPresenter.m | 10 ++++ .../RNNNavigationControllerPresenterTest.m | 57 ------------------- .../RNNViewControllerPresenterTest.m | 30 ++++++++++ .../UINavigationController+RNNOptionsTest.m | 39 ------------- .../UIViewController+LayoutProtocolTest.m | 38 +++++++++++++ lib/ios/UINavigationController+RNNOptions.h | 2 - lib/ios/UINavigationController+RNNOptions.m | 20 ------- lib/ios/UIViewController+RNNOptions.h | 2 + lib/ios/UIViewController+RNNOptions.m | 20 +++++++ 10 files changed, 100 insertions(+), 127 deletions(-) diff --git a/lib/ios/RNNNavigationControllerPresenter.m b/lib/ios/RNNNavigationControllerPresenter.m index 31f32ac21ae..a326bcb29ef 100644 --- a/lib/ios/RNNNavigationControllerPresenter.m +++ b/lib/ios/RNNNavigationControllerPresenter.m @@ -46,14 +46,10 @@ - (void)applyOptions:(RNNNavigationOptions *)options { [navigationController rnn_setNavigationBarLargeTitleFontFamily:[options.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.largeTitle.fontSize getWithDefaultValue:nil] color:[options.topBar.largeTitle.color getWithDefaultValue:nil]]; [navigationController rnn_setNavigationBarFontFamily:[options.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.title.fontSize getWithDefaultValue:nil] color:[options.topBar.title.color getWithDefaultValue:nil]]; [navigationController rnn_setBackButtonColor:[options.topBar.backButton.color getWithDefaultValue:nil]]; - [navigationController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""]; } - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options { [super applyOptionsOnWillMoveToParentViewController:options]; - - RNNNavigationController* navigationController = self.bindedViewController; - [navigationController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""]; } - (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options { @@ -122,11 +118,6 @@ - (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavig [navigationController rnn_setNavigationBarLargeTitleVisible:newOptions.topBar.largeTitle.visible.get]; } - if (newOptions.topBar.backButton.icon.hasValue || newOptions.topBar.backButton.showTitle.hasValue || newOptions.topBar.backButton.color.hasValue || newOptions.topBar.backButton.title.hasValue) { - [navigationController rnn_setBackButtonIcon:[newOptions.topBar.backButton.icon getWithDefaultValue:nil] withColor:[newOptions.topBar.backButton.color getWithDefaultValue:nil] title:[newOptions.topBar.backButton.showTitle getWithDefaultValue:YES] ? [newOptions.topBar.backButton.title getWithDefaultValue:nil] : @""]; - - } - if (newOptions.topBar.backButton.color.hasValue) { [navigationController rnn_setBackButtonColor:newOptions.topBar.backButton.color.get]; } diff --git a/lib/ios/RNNViewControllerPresenter.m b/lib/ios/RNNViewControllerPresenter.m index fe7f87a3640..5d12c2bcaf7 100644 --- a/lib/ios/RNNViewControllerPresenter.m +++ b/lib/ios/RNNViewControllerPresenter.m @@ -28,6 +28,12 @@ - (void)bindViewController:(UIViewController *)bindedViewCont _navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.bindedViewController componentRegistry:_componentRegistry]; } +- (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options { + [super applyOptionsOnWillMoveToParentViewController:options]; + UIViewController* viewController = self.bindedViewController; + [viewController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""]; +} + - (void)applyOptions:(RNNNavigationOptions *)options { [super applyOptions:options]; @@ -150,6 +156,10 @@ - (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavig if (newOptions.topBar.title.component.name.hasValue) { [self setCustomNavigationTitleView:newOptions perform:nil]; } + + if (newOptions.topBar.backButton.icon.hasValue || newOptions.topBar.backButton.showTitle.hasValue || newOptions.topBar.backButton.color.hasValue || newOptions.topBar.backButton.title.hasValue) { + [viewController rnn_setBackButtonIcon:[newOptions.topBar.backButton.icon getWithDefaultValue:nil] withColor:[newOptions.topBar.backButton.color getWithDefaultValue:nil] title:[newOptions.topBar.backButton.showTitle getWithDefaultValue:YES] ? [newOptions.topBar.backButton.title getWithDefaultValue:nil] : @""]; + } } - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock { diff --git a/lib/ios/ReactNativeNavigationTests/RNNNavigationControllerPresenterTest.m b/lib/ios/ReactNativeNavigationTests/RNNNavigationControllerPresenterTest.m index aa111ec9ecf..aeb5403a287 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNNavigationControllerPresenterTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNNavigationControllerPresenterTest.m @@ -35,63 +35,6 @@ - (void)testApplyOptions_shouldSetBackButtonColor_withColor { [_bindedViewController verify]; } - -- (void)testApplyOptions_shouldSetBackButtonOnBindedViewController_withTitle { - Text* title = [[Text alloc] initWithValue:@"Title"]; - self.options.topBar.backButton.title = title; - [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:title.get]; - [self.uut applyOptions:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptions_shouldSetBackButtonOnBindedViewController_withHideTitle { - Text* title = [[Text alloc] initWithValue:@"Title"]; - self.options.topBar.backButton.title = title; - self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)]; - [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:@""]; - [self.uut applyOptions:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptions_shouldSetBackButtonOnBindedViewController_withIcon { - Image* image = [[Image alloc] initWithValue:[UIImage new]]; - self.options.topBar.backButton.icon = image; - [[_bindedViewController expect] rnn_setBackButtonIcon:image.get withColor:nil title:nil]; - [self.uut applyOptions:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withTitle { - Text* title = [[Text alloc] initWithValue:@"Title"]; - self.options.topBar.backButton.title = title; - [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:title.get]; - [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withHideTitle { - Text* title = [[Text alloc] initWithValue:@"Title"]; - self.options.topBar.backButton.title = title; - self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)]; - [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:@""]; - [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withIcon { - Image* image = [[Image alloc] initWithValue:[UIImage new]]; - self.options.topBar.backButton.icon = image; - [[_bindedViewController expect] rnn_setBackButtonIcon:image.get withColor:nil title:nil]; - [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; - [_bindedViewController verify]; -} - -- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withDefaultValues { - [[_bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:nil]; - [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; - [_bindedViewController verify]; -} - - (void)testApplyOptionsBeforePoppingShouldSetTopBarBackgroundForPoppingViewController { _options.topBar.background.color = [[Color alloc] initWithValue:[UIColor redColor]]; diff --git a/lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m b/lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m index 4240f590570..34d30ab2a9e 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m @@ -173,6 +173,36 @@ - (void)testRenderComponentsCreateReactViewWithBindedComponentId { XCTAssertEqual(self.uut.bindedComponentId, @"componentId"); } +- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withTitle { + Text* title = [[Text alloc] initWithValue:@"Title"]; + self.options.topBar.backButton.title = title; + [[(id)self.bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:title.get]; + [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; + [(id)self.bindedViewController verify]; +} + +- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withHideTitle { + Text* title = [[Text alloc] initWithValue:@"Title"]; + self.options.topBar.backButton.title = title; + self.options.topBar.backButton.showTitle = [[Bool alloc] initWithValue:@(0)]; + [[(id)self.bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:@""]; + [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; + [(id)self.bindedViewController verify]; +} + +- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withIcon { + Image* image = [[Image alloc] initWithValue:[UIImage new]]; + self.options.topBar.backButton.icon = image; + [[(id)self.bindedViewController expect] rnn_setBackButtonIcon:image.get withColor:nil title:nil]; + [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; + [(id)self.bindedViewController verify]; +} + +- (void)testApplyOptionsOnWillMoveToParent_shouldSetBackButtonOnBindedViewController_withDefaultValues { + [[(id)self.bindedViewController expect] rnn_setBackButtonIcon:nil withColor:nil title:nil]; + [self.uut applyOptionsOnWillMoveToParentViewController:self.options]; + [(id)self.bindedViewController verify]; +} - (RNNLayoutInfo *)createLayoutInfoWithComponentId:(NSString *)componentId { diff --git a/lib/ios/ReactNativeNavigationTests/UINavigationController+RNNOptionsTest.m b/lib/ios/ReactNativeNavigationTests/UINavigationController+RNNOptionsTest.m index 23b0ab6258b..b6842fe3a98 100644 --- a/lib/ios/ReactNativeNavigationTests/UINavigationController+RNNOptionsTest.m +++ b/lib/ios/ReactNativeNavigationTests/UINavigationController+RNNOptionsTest.m @@ -11,43 +11,4 @@ - (void)setUp { [super setUp]; } -- (void)testSetBackButtonIcon_withColor_shouldSetColor { - UIViewController* viewController = [UIViewController new]; - UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController]; - UIColor* color = [UIColor blackColor]; - - [nav rnn_setBackButtonIcon:nil withColor:color title:nil]; - XCTAssertEqual(color, viewController.navigationItem.backBarButtonItem.tintColor); -} - -- (void)testSetBackButtonIcon_withColor_shouldSetTitle { - UIViewController* viewController = [UIViewController new]; - UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController]; - NSString* title = @"Title"; - - [nav rnn_setBackButtonIcon:nil withColor:nil title:title]; - XCTAssertEqual(title, viewController.navigationItem.backBarButtonItem.title); -} - -- (void)testSetBackButtonIcon_withColor_shouldSetIcon { - UIViewController* viewController = [UIViewController new]; - UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController]; - UIImage* icon = [UIImage new]; - - [nav rnn_setBackButtonIcon:icon withColor:nil title:nil]; - XCTAssertEqual(icon, viewController.navigationItem.backBarButtonItem.image); -} - -- (void)testSetBackButtonIcon_shouldSetTitleOnPreviousViewControllerIfExists { - UIViewController* viewController = [UIViewController new]; - UIViewController* viewController2 = [UIViewController new]; - UINavigationController* nav = [[UINavigationController alloc] init]; - [nav setViewControllers:@[viewController, viewController2]]; - NSString* title = @"Title"; - - [nav rnn_setBackButtonIcon:nil withColor:nil title:title]; - XCTAssertEqual(title, viewController.navigationItem.backBarButtonItem.title); -} - - @end diff --git a/lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m b/lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m index b8383f46a3a..5ad0c17a0ea 100644 --- a/lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m +++ b/lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m @@ -1,6 +1,7 @@ #import #import #import "UIViewController+LayoutProtocol.h" +#import "UIViewController+RNNOptions.h" #import "RNNViewControllerPresenter.h" #import "RCTConvert+Modal.h" @@ -39,5 +40,42 @@ - (void)testInitWithLayoutInfoShouldSetChildViewControllers { XCTAssertEqual(uut.viewControllers[1], child2); } +- (void)testSetBackButtonIcon_withColor_shouldSetColor { + UIViewController* uut = [UIViewController new]; + [[UINavigationController alloc] initWithRootViewController:uut]; + UIColor* color = [UIColor blackColor]; + + [uut rnn_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 rnn_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 rnn_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 rnn_setBackButtonIcon:nil withColor:nil title:title]; + XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title); +} @end diff --git a/lib/ios/UINavigationController+RNNOptions.h b/lib/ios/UINavigationController+RNNOptions.h index 7b7e5dc5302..27a678282d9 100644 --- a/lib/ios/UINavigationController+RNNOptions.h +++ b/lib/ios/UINavigationController+RNNOptions.h @@ -24,8 +24,6 @@ - (void)rnn_setNavigationBarClipsToBounds:(BOOL)clipsToBounds; -- (void)rnn_setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title; - - (void)rnn_setNavigationBarLargeTitleVisible:(BOOL)visible; - (void)rnn_setNavigationBarLargeTitleFontFamily:(NSString *)fontFamily fontSize:(NSNumber *)fontSize color:(UIColor *)color; diff --git a/lib/ios/UINavigationController+RNNOptions.m b/lib/ios/UINavigationController+RNNOptions.m index 5a6c2e9c4a1..9630ac4843d 100644 --- a/lib/ios/UINavigationController+RNNOptions.m +++ b/lib/ios/UINavigationController+RNNOptions.m @@ -1,6 +1,5 @@ #import "UINavigationController+RNNOptions.h" #import "RNNFontAttributesCreator.h" -#import "UIImage+tint.h" const NSInteger BLUR_TOPBAR_TAG = 78264802; @@ -96,25 +95,6 @@ - (void)rnn_setNavigationBarBlur:(BOOL)blur { } } -- (void)rnn_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.navigationBar setBackIndicatorImage:[UIImage new]]; - [self.navigationBar setBackIndicatorTransitionMaskImage:[UIImage new]]; - } - - UIViewController *lastViewControllerInStack = self.viewControllers.count > 1 ? [self.viewControllers objectAtIndex:self.viewControllers.count-2] : self.topViewController; - - backItem.title = title ? title : lastViewControllerInStack.navigationItem.title; - backItem.tintColor = color; - - lastViewControllerInStack.navigationItem.backBarButtonItem = backItem; -} - - (void)rnn_setBackButtonColor:(UIColor *)color { self.navigationBar.tintColor = color; } diff --git a/lib/ios/UIViewController+RNNOptions.h b/lib/ios/UIViewController+RNNOptions.h index c0b8ac51174..a44b2be579b 100644 --- a/lib/ios/UIViewController+RNNOptions.h +++ b/lib/ios/UIViewController+RNNOptions.h @@ -34,6 +34,8 @@ - (void)rnn_setInterceptTouchOutside:(BOOL)interceptTouchOutside; +- (void)rnn_setBackButtonIcon:(UIImage *)icon withColor:(UIColor *)color title:(NSString *)title; + - (BOOL)isModal; @end diff --git a/lib/ios/UIViewController+RNNOptions.m b/lib/ios/UIViewController+RNNOptions.m index d63ea188a77..b16145b4cb4 100644 --- a/lib/ios/UIViewController+RNNOptions.m +++ b/lib/ios/UIViewController+RNNOptions.m @@ -1,5 +1,6 @@ #import "UIViewController+RNNOptions.h" #import +#import "UIImage+tint.h" #define kStatusBarAnimationDuration 0.35 const NSInteger BLUR_STATUS_TAG = 78264801; @@ -162,4 +163,23 @@ - (void)rnn_setInterceptTouchOutside:(BOOL)interceptTouchOutside { } } +- (void)rnn_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 objectAtIndex:self.navigationController.viewControllers.count-2] : self.navigationController.topViewController; + + backItem.title = title ? title : lastViewControllerInStack.navigationItem.title; + backItem.tintColor = color; + + lastViewControllerInStack.navigationItem.backBarButtonItem = backItem; +} + @end