diff --git a/Routable/Routable.h b/Routable/Routable.h index de76bd8..6632f30 100644 --- a/Routable/Routable.h +++ b/Routable/Routable.h @@ -77,6 +77,21 @@ typedef void (^RouterOpenCallback)(NSDictionary *params); defaultParams: (NSDictionary *)defaultParams isRoot: (BOOL)isRoot isModal: (BOOL)isModal; +/** + @return A new instance of `UPRouterOptions` with its properties explicitly set + @param presentationStyle The `UIModalPresentationStyle` attached to the mapped `UIViewController` + @param transitionStyle The `UIModalTransitionStyle` attached to the mapped `UIViewController` + @param defaultParams The default parameters which are passed when opening the URL + @param isRoot The boolean `shouldOpenAsRootViewController` property is set to + @param isModal The boolean that sets a modal presentation format + @param shouldDismissPresentedViewController The boolean indicating whether an already existing presentedViewController should be dismissed before presenting a new one + */ ++ (instancetype)routerOptionsWithPresentationStyle: (UIModalPresentationStyle)presentationStyle + transitionStyle: (UIModalTransitionStyle)transitionStyle + defaultParams: (NSDictionary *)defaultParams + isRoot: (BOOL)isRoot + isModal: (BOOL)isModal + shouldDismissPresentedViewController: (BOOL)shouldDismissPresentedViewController; /** @return A new instance of `UPRouterOptions` with its properties set to default */ @@ -108,6 +123,10 @@ typedef void (^RouterOpenCallback)(NSDictionary *params); @return A new instance of `UPRouterOptions`, setting the `shouldOpenAsRootViewController` property to `YES` */ + (instancetype)routerOptionsAsRoot; +/** + @return A new instance of `UPRouterOptions`, setting the `shouldDismissPresentedViewController` property to `NO` + */ ++ (instancetype)routerOptionsAsKeepPresentedViewController; //previously supported /** @@ -138,6 +157,11 @@ typedef void (^RouterOpenCallback)(NSDictionary *params); @return A new instance of `UPRouterOptions`, setting the `shouldOpenAsRootViewController` property to `YES` */ + (instancetype)root; +/** + @remarks not idiomatic objective-c naming for allocation and initialization, see +routerOptionsAsRoot + @return A new instance of `UPRouterOptions`, setting the `shouldDismissPresentedViewController` property to `NO` + */ ++ (instancetype)keepPresentedViewController; /** @remarks not idiomatic objective-c naming; overrides getter to wrap around setter @@ -167,6 +191,11 @@ typedef void (^RouterOpenCallback)(NSDictionary *params); @return A new instance of `UPRouterOptions`, setting the `shouldOpenAsRootViewController` property to `YES` */ - (UPRouterOptions *)root; +/** + @remarks not idiomatic objective-c naming; wraps around setter + @return A new instance of `UPRouterOptions`, setting the `shouldDismissPresentedViewController` property to `NO` + */ +- (UPRouterOptions *)keepPresentedViewController; ///------------------------------- /// @name Properties @@ -192,6 +221,10 @@ typedef void (^RouterOpenCallback)(NSDictionary *params); The property determining if the mapped `UIViewController` instance should be set as the root view controller of the router's `UINavigationController` instance. */ @property (readwrite, nonatomic, assign) BOOL shouldOpenAsRootViewController; +/** + The property determining if a possibly already presented view controller should be dismissed before presenting the new one. Defaults to 'YES'. + */ +@property (readwrite, nonatomic, assign) BOOL shouldDismissPresentedViewController; @end diff --git a/Routable/Routable.m b/Routable/Routable.m index 61c91ae..09b9438 100644 --- a/Routable/Routable.m +++ b/Routable/Routable.m @@ -78,18 +78,35 @@ @interface UPRouterOptions () @implementation UPRouterOptions +//Backwards compatibility ++ (instancetype)routerOptionsWithPresentationStyle: (UIModalPresentationStyle)presentationStyle + transitionStyle: (UIModalTransitionStyle)transitionStyle + defaultParams: (NSDictionary *)defaultParams + isRoot: (BOOL)isRoot + isModal: (BOOL)isModal +{ + return [self routerOptionsWithPresentationStyle:presentationStyle + transitionStyle:transitionStyle + defaultParams:defaultParams + isRoot:isRoot + isModal:isModal + shouldDismissPresentedViewController:YES]; +} //Explicit construction + (instancetype)routerOptionsWithPresentationStyle: (UIModalPresentationStyle)presentationStyle transitionStyle: (UIModalTransitionStyle)transitionStyle defaultParams: (NSDictionary *)defaultParams isRoot: (BOOL)isRoot - isModal: (BOOL)isModal { + isModal: (BOOL)isModal + shouldDismissPresentedViewController: (BOOL)shouldDismissPresentedViewController +{ UPRouterOptions *options = [[UPRouterOptions alloc] init]; options.presentationStyle = presentationStyle; options.transitionStyle = transitionStyle; options.defaultParams = defaultParams; options.shouldOpenAsRootViewController = isRoot; options.modal = isModal; + options.shouldDismissPresentedViewController = shouldDismissPresentedViewController; return options; } //Default construction; like [NSArray array] @@ -98,7 +115,8 @@ + (instancetype)routerOptions { transitionStyle:UIModalTransitionStyleCoverVertical defaultParams:nil isRoot:NO - isModal:NO]; + isModal:NO + shouldDismissPresentedViewController:YES]; } //Custom class constructors, with heavier Objective-C accent @@ -107,35 +125,48 @@ + (instancetype)routerOptionsAsModal { transitionStyle:UIModalTransitionStyleCoverVertical defaultParams:nil isRoot:NO - isModal:YES]; + isModal:YES + shouldDismissPresentedViewController:YES]; } + (instancetype)routerOptionsWithPresentationStyle:(UIModalPresentationStyle)style { return [self routerOptionsWithPresentationStyle:style transitionStyle:UIModalTransitionStyleCoverVertical defaultParams:nil isRoot:NO - isModal:NO]; + isModal:NO + shouldDismissPresentedViewController:YES]; } + (instancetype)routerOptionsWithTransitionStyle:(UIModalTransitionStyle)style { return [self routerOptionsWithPresentationStyle:UIModalPresentationNone transitionStyle:style defaultParams:nil isRoot:NO - isModal:NO]; + isModal:NO + shouldDismissPresentedViewController:YES]; } + (instancetype)routerOptionsForDefaultParams:(NSDictionary *)defaultParams { return [self routerOptionsWithPresentationStyle:UIModalPresentationNone transitionStyle:UIModalTransitionStyleCoverVertical defaultParams:defaultParams isRoot:NO - isModal:NO]; + isModal:NO + shouldDismissPresentedViewController:YES]; } + (instancetype)routerOptionsAsRoot { return [self routerOptionsWithPresentationStyle:UIModalPresentationNone transitionStyle:UIModalTransitionStyleCoverVertical defaultParams:nil isRoot:YES - isModal:NO]; + isModal:NO + shouldDismissPresentedViewController:YES]; +} ++ (instancetype)routerOptionsAsKeepPresentedViewController { + return [self routerOptionsWithPresentationStyle:UIModalPresentationNone + transitionStyle:UIModalTransitionStyleCoverVertical + defaultParams:nil + isRoot:NO + isModal:NO + shouldDismissPresentedViewController:NO]; } //Exposed methods previously supported @@ -154,6 +185,9 @@ + (instancetype)forDefaultParams:(NSDictionary *)defaultParams { + (instancetype)root { return [self routerOptionsAsRoot]; } ++ (instancetype)keepPresentedViewController { + return [self routerOptionsAsKeepPresentedViewController]; +} //Wrappers around setters (to continue DSL-like syntax) - (UPRouterOptions *)modal { @@ -176,6 +210,10 @@ - (UPRouterOptions *)root { [self setShouldOpenAsRootViewController:YES]; return self; } +- (UPRouterOptions *)keepPresentedViewController { + [self setShouldDismissPresentedViewController:NO]; + return self; +} @end @interface UPRouter () @@ -268,15 +306,21 @@ - (void)open:(NSString *)url animated:(BOOL)animated { UIViewController *controller = [self controllerForRouterParams:params]; - if (self.navigationController.presentedViewController) { + if (self.navigationController.presentedViewController && [options shouldDismissPresentedViewController]) { [self.navigationController dismissViewControllerAnimated:animated completion:nil]; } if ([options isModal]) { if ([controller.class isSubclassOfClass:UINavigationController.class]) { - [self.navigationController presentViewController:controller - animated:animated - completion:nil]; + UIViewController* controllerToPresentOn = self.navigationController; + + if (self.navigationController.presentedViewController) { + controllerToPresentOn = self.navigationController.presentedViewController; + } + + [controllerToPresentOn presentViewController:controller + animated:animated + completion:nil]; } else { UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];