Skip to content

Commit

Permalink
Explicit attaching and detaching viewControllers in store (#4947)
Browse files Browse the repository at this point in the history
* Explicitly attach and detach viewControllers in store
* Stop registering components in commands handler
  • Loading branch information
yogevbd authored and guyca committed Apr 8, 2019
1 parent 7c43262 commit 2830059
Show file tree
Hide file tree
Showing 40 changed files with 369 additions and 564 deletions.
4 changes: 4 additions & 0 deletions lib/ios/RNNBasePresenter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#import "RNNNavigationOptions.h"

typedef void (^RNNReactViewReadyCompletionBlock)(void);

@interface RNNBasePresenter : NSObject

@property (nonatomic, weak) id bindedViewController;
Expand All @@ -16,4 +18,6 @@

- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions;

- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;

@end
7 changes: 7 additions & 0 deletions lib/ios/RNNBasePresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import "UIViewController+RNNOptions.h"
#import "RNNTabBarItemCreator.h"
#import "RNNReactComponentRegistry.h"
#import "UIViewController+LayoutProtocol.h"

@interface RNNBasePresenter ()
@property (nonatomic, strong) RNNReactComponentRegistry* componentRegistry;
Expand Down Expand Up @@ -134,5 +135,11 @@ - (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavig
}
}

- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
if (readyBlock) {
readyBlock();
readyBlock = nil;
}
}

@end
32 changes: 11 additions & 21 deletions lib/ios/RNNCommandsHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#import "RNNDefaultOptionsHelper.h"
#import "UIViewController+RNNOptions.h"
#import "React/RCTI18nUtil.h"
#import "UIViewController+LayoutProtocol.h"

static NSString* const setRoot = @"setRoot";
static NSString* const setStackRoot = @"setStackRoot";
Expand Down Expand Up @@ -73,9 +74,8 @@ - (void)setRoot:(NSDictionary*)layout commandId:(NSString*)commandId completion:
}

[_modalManager dismissAllModalsAnimated:NO];
[_store removeAllComponentsFromWindow:_mainWindow];

UIViewController<RNNLayoutProtocol> *vc = [_controllerFactory createLayout:layout[@"root"]];
UIViewController *vc = [_controllerFactory createLayout:layout[@"root"]];

[vc renderTreeAndWait:[vc.resolveOptions.animations.setRoot.waitForRender getWithDefaultValue:NO] perform:^{
_mainWindow.rootViewController = vc;
Expand Down Expand Up @@ -114,7 +114,7 @@ - (void)setDefaultOptions:(NSDictionary*)optionsDict completion:(RNNTransitionCo
- (void)push:(NSString*)componentId commandId:(NSString*)commandId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
[self assertReady];

UIViewController<RNNLayoutProtocol> *newVc = [_controllerFactory createLayout:layout];
UIViewController *newVc = [_controllerFactory createLayout:layout];
UIViewController *fromVC = [_store findComponentForId:componentId];

if ([[newVc.resolveOptions.preview.reactTag getWithDefaultValue:@(0)] floatValue] > 0) {
Expand Down Expand Up @@ -172,7 +172,7 @@ - (void)push:(NSString*)componentId commandId:(NSString*)commandId layout:(NSDic
- (void)setStackRoot:(NSString*)componentId commandId:(NSString*)commandId children:(NSArray*)children completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
[self assertReady];

NSArray<RNNLayoutProtocol> *childViewControllers = [_controllerFactory createChildrenLayout:children];
NSArray *childViewControllers = [_controllerFactory createChildrenLayout:children];
for (UIViewController<RNNLayoutProtocol>* viewController in childViewControllers) {
[viewController renderTreeAndWait:NO perform:nil];
}
Expand Down Expand Up @@ -207,7 +207,6 @@ - (void)pop:(NSString*)componentId commandId:(NSString*)commandId mergeOptions:(
}

[_stackManager pop:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^{
[_store removeComponent:componentId];
[_eventEmitter sendOnNavigationCommandCompletion:pop commandId:commandId params:@{@"componentId": componentId}];
completion();
} rejection:rejection];
Expand All @@ -221,7 +220,6 @@ - (void)popTo:(NSString*)componentId commandId:(NSString*)commandId mergeOptions

[_stackManager popTo:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
[_eventEmitter sendOnNavigationCommandCompletion:popTo commandId:commandId params:@{@"componentId": componentId}];
[self removePopedViewControllers:poppedViewControllers];
completion();
} rejection:rejection];
}
Expand All @@ -239,7 +237,7 @@ - (void)popToRoot:(NSString*)componentId commandId:(NSString*)commandId mergeOpt
}];

[_stackManager popToRoot:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
[self removePopedViewControllers:poppedViewControllers];

} rejection:^(NSString *code, NSString *message, NSError *error) {

}];
Expand All @@ -250,7 +248,7 @@ - (void)popToRoot:(NSString*)componentId commandId:(NSString*)commandId mergeOpt
- (void)showModal:(NSDictionary*)layout commandId:(NSString *)commandId completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
[self assertReady];

UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayout:layout];
UIViewController *newVc = [_controllerFactory createLayout:layout];

[newVc renderTreeAndWait:[newVc.resolveOptions.animations.showModal.waitForRender getWithDefaultValue:NO] perform:^{
[_modalManager showModal:newVc animated:[newVc.getCurrentChild.resolveOptions.animations.showModal.enable getWithDefaultValue:YES] hasCustomAnimation:newVc.getCurrentChild.resolveOptions.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
Expand All @@ -263,7 +261,7 @@ - (void)showModal:(NSDictionary*)layout commandId:(NSString *)commandId completi
- (void)dismissModal:(NSString*)componentId commandId:(NSString*)commandId mergeOptions:(NSDictionary *)mergeOptions completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject {
[self assertReady];

UIViewController<RNNParentProtocol> *modalToDismiss = (UIViewController<RNNParentProtocol>*)[_store findComponentForId:componentId];
UIViewController *modalToDismiss = (UIViewController *)[_store findComponentForId:componentId];

if (!modalToDismiss.isModal) {
[RNNErrorHandler reject:reject withErrorCode:1013 errorDescription:@"component is not a modal"];
Expand All @@ -272,9 +270,7 @@ - (void)dismissModal:(NSString*)componentId commandId:(NSString*)commandId merge

RNNNavigationOptions *options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
[modalToDismiss.getCurrentChild overrideOptions:options];

[self removePopedViewControllers:modalToDismiss.navigationController.viewControllers];


[CATransaction begin];
[CATransaction setCompletionBlock:^{
[_eventEmitter sendOnNavigationCommandCompletion:dismissModal commandId:commandId params:@{@"componentId": componentId}];
Expand Down Expand Up @@ -302,7 +298,7 @@ - (void)dismissAllModals:(NSDictionary *)mergeOptions commandId:(NSString*)comma
- (void)showOverlay:(NSDictionary *)layout commandId:(NSString*)commandId completion:(RNNTransitionCompletionBlock)completion {
[self assertReady];

UIViewController<RNNParentProtocol>* overlayVC = [_controllerFactory createLayout:layout];
UIViewController* overlayVC = [_controllerFactory createLayout:layout];
[overlayVC renderTreeAndWait:NO perform:^{
UIWindow* overlayWindow = [[RNNOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
overlayWindow.rootViewController = overlayVC;
Expand All @@ -326,12 +322,6 @@ - (void)dismissOverlay:(NSString*)componentId commandId:(NSString*)commandId com

#pragma mark - private

- (void)removePopedViewControllers:(NSArray*)viewControllers {
for (UIViewController *popedVC in viewControllers) {
[_store removeComponentByViewControllerInstance:popedVC];
}
}

- (void)assertReady {
if (!_store.isReadyToReceiveCommands) {
[[NSException exceptionWithName:@"BridgeNotLoadedError"
Expand All @@ -343,13 +333,13 @@ - (void)assertReady {

#pragma mark - RNNModalManagerDelegate

- (void)dismissedModal:(UIViewController<RNNParentProtocol> *)viewController {
- (void)dismissedModal:(UIViewController *)viewController {
[_eventEmitter sendModalsDismissedEvent:viewController.layoutInfo.componentId numberOfModalsDismissed:@(1)];
}

- (void)dismissedMultipleModals:(NSArray *)viewControllers {
if (viewControllers && viewControllers.count) {
[_eventEmitter sendModalsDismissedEvent:((UIViewController<RNNParentProtocol> *)viewControllers.lastObject).layoutInfo.componentId numberOfModalsDismissed:@(viewControllers.count)];
[_eventEmitter sendModalsDismissedEvent:((UIViewController *)viewControllers.lastObject).layoutInfo.componentId numberOfModalsDismissed:@(viewControllers.count)];
}
}

Expand Down
6 changes: 3 additions & 3 deletions lib/ios/RNNControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#import "RNNRootViewCreator.h"
#import "RNNStore.h"
#import "RNNEventEmitter.h"
#import "RNNParentProtocol.h"
#import "RNNReactComponentRegistry.h"
#import "RNNNavigationOptions.h"

@interface RNNControllerFactory : NSObject

Expand All @@ -15,9 +15,9 @@
componentRegistry:(RNNReactComponentRegistry *)componentRegistry
andBridge:(RCTBridge*)bridge;

- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout;
- (UIViewController *)createLayout:(NSDictionary*)layout;

- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children;
- (NSArray *)createChildrenLayout:(NSArray*)children;

@property (nonatomic, strong) RNNEventEmitter *eventEmitter;

Expand Down
50 changes: 27 additions & 23 deletions lib/ios/RNNControllerFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
return self;
}

- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout {
UIViewController<RNNParentProtocol>* layoutViewController = [self fromTree:layout];
- (UIViewController *)createLayout:(NSDictionary*)layout {
UIViewController* layoutViewController = [self fromTree:layout];
return layoutViewController;
}

Expand All @@ -58,10 +58,10 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator

# pragma mark private

- (UIViewController<RNNParentProtocol> *)fromTree:(NSDictionary*)json {
- (UIViewController *)fromTree:(NSDictionary*)json {
RNNLayoutNode* node = [RNNLayoutNode create:json];

UIViewController<RNNParentProtocol> *result;
UIViewController *result;

if (node.isComponent) {
result = [self createComponent:node];
Expand Down Expand Up @@ -106,23 +106,23 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
if (!result) {
@throw [NSException exceptionWithName:@"UnknownControllerType" reason:[@"Unknown controller type " stringByAppendingString:node.type] userInfo:nil];
}

[_store setComponent:result componentId:node.nodeId];
result.store = _store;

return result;
}

- (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
- (UIViewController *)createComponent:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];

RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];

return (UIViewController<RNNParentProtocol> *)component;
return (UIViewController *)component;
}

- (UIViewController<RNNParentProtocol> *)createExternalComponent:(RNNLayoutNode*)node {
- (UIViewController *)createExternalComponent:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
Expand All @@ -132,61 +132,64 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
RNNRootViewController* component = [[RNNRootViewController alloc] initExternalComponentWithLayoutInfo:layoutInfo eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];
[component bindViewController:externalVC];

return (UIViewController<RNNParentProtocol> *)component;
return (UIViewController *)component;
}


- (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
- (UIViewController *)createStack:(RNNLayoutNode*)node {
RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo creator:_creator childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];
[stack setViewControllers:childViewControllers];

return stack;
}

-(UIViewController<RNNParentProtocol> *)createTabs:(RNNLayoutNode*)node {
-(UIViewController *)createTabs:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNTabBarPresenter* presenter = [[RNNTabBarPresenter alloc] init];

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNTabBarController* tabsController = [[RNNTabBarController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];
RNNTabBarController* tabsController = [[RNNTabBarController alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];
[tabsController setViewControllers:childViewControllers];

return tabsController;
}

- (UIViewController<RNNParentProtocol> *)createTopTabs:(RNNLayoutNode*)node {
- (UIViewController *)createTopTabs:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNTopTabsViewController* topTabsController = [[RNNTopTabsViewController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
RNNTopTabsViewController* topTabsController = [[RNNTopTabsViewController alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];
[topTabsController setViewControllers:childViewControllers];

return topTabsController;
}

- (UIViewController<RNNParentProtocol> *)createSideMenu:(RNNLayoutNode*)node {
- (UIViewController *)createSideMenu:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNSideMenuPresenter* presenter = [[RNNSideMenuPresenter alloc] init];

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNSideMenuController *sideMenu = [[RNNSideMenuController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
RNNSideMenuController *sideMenu = [[RNNSideMenuController alloc] initWithLayoutInfo:layoutInfo creator:_creator childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];

return sideMenu;
}


- (UIViewController<RNNParentProtocol> *)createSideMenuChild:(RNNLayoutNode*)node type:(RNNSideMenuChildType)type {
UIViewController<RNNParentProtocol>* childVc = [self fromTree:node.children[0]];
- (UIViewController *)createSideMenuChild:(RNNLayoutNode*)node type:(RNNSideMenuChildType)type {
UIViewController* childVc = [self fromTree:node.children[0]];
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;

Expand All @@ -195,15 +198,16 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
return sideMenuChild;
}

- (UIViewController<RNNParentProtocol> *)createSplitView:(RNNLayoutNode*)node {
- (UIViewController *)createSplitView:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
RNNSplitViewControllerPresenter* presenter = [[RNNSplitViewControllerPresenter alloc] init];

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNSplitViewController* splitViewController = [[RNNSplitViewController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];

RNNSplitViewController* splitViewController = [[RNNSplitViewController alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:presenter eventEmitter:_eventEmitter];
[splitViewController bindChildViewControllers:childViewControllers];

return splitViewController;
}

Expand Down
15 changes: 10 additions & 5 deletions lib/ios/RNNLayoutProtocol.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#import "RNNLayoutInfo.h"
#import "RNNLeafProtocol.h"
#import "RNNBasePresenter.h"
#import "RNNRootViewCreator.h"
#import "RNNEventEmitter.h"

typedef void (^RNNReactViewReadyCompletionBlock)(void);

@protocol RNNLayoutProtocol <NSObject, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>

@required

@property (nonatomic, retain) RNNBasePresenter* presenter;
@property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
@property (nonatomic, strong) RNNNavigationOptions* options;
@property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
- (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo
creator:(id<RNNRootViewCreator>)creator
options:(RNNNavigationOptions *)options
defaultOptions:(RNNNavigationOptions *)defaultOptions
presenter:(RNNBasePresenter *)presenter
eventEmitter:(RNNEventEmitter *)eventEmitter;

- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;

Expand All @@ -25,4 +28,6 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);

- (void)overrideOptions:(RNNNavigationOptions *)options;

- (void)onChildWillAppear;

@end
3 changes: 2 additions & 1 deletion lib/ios/RNNModalManager.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "RNNModalManager.h"
#import "RNNRootViewController.h"
#import "RNNAnimationsTransitionDelegate.h"
#import "RNNLayoutProtocol.h"

@implementation RNNModalManager {
NSMutableArray* _pendingModalIdsToDismiss;
Expand Down Expand Up @@ -61,7 +62,7 @@ -(void)dismissAllModalsAnimated:(BOOL)animated {


-(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
UIViewController<RNNParentProtocol> *modalToDismiss = [_pendingModalIdsToDismiss lastObject];
UIViewController<RNNLayoutProtocol> *modalToDismiss = [_pendingModalIdsToDismiss lastObject];
RNNNavigationOptions* options = modalToDismiss.resolveOptions;

if(!modalToDismiss) {
Expand Down
1 change: 1 addition & 0 deletions lib/ios/RNNNavigationButtons.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#import "UIImage+tint.h"
#import "RNNRootViewController.h"
#import "UIImage+insets.h"
#import "UIViewController+LayoutProtocol.h"

@interface RNNNavigationButtons()

Expand Down
Loading

0 comments on commit 2830059

Please sign in to comment.