Skip to content

Commit

Permalink
A receiver of dismiss may be not visible (current) view controller
Browse files Browse the repository at this point in the history
  • Loading branch information
artemstepanenko committed Jan 21, 2015
1 parent 3f56939 commit d3a48cc
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CrossNavigation/CNViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
/**
Dismisses a view controller that was presented modally by a receiver in a defined direction.
If a receiver is not a last view controller in a stack, it dismisses all subsequent view controllers. So when animation is finished, the receiver becomes a visible view controller. A transition occurs from the visible view controller to the receiver.
@param direction Determines in what direction view controller will be dismissed
@param animated Determines whether the view controller will be dismissed animated or not
@param completion The block to execute after the view controller is dismissed. May be nil.
Expand Down
65 changes: 55 additions & 10 deletions CrossNavigation/CNViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#import "CNInteractiveTransition.h"
#import "CNPanGestureHandler.h"
#import "CNTimer.h"
#import <QuartzCore/QuartzCore.h>

@interface CNViewController () <CNPanGestureHandlerDelegate>

Expand Down Expand Up @@ -102,6 +103,7 @@ - (void)dismissViewControllerToDirection:(CNDirection)direction
}

if (self.presentedViewController) {
// rather tricky case since default behaviour is buggy
[self dismissInvisibleViewControllerToDirection:direction animated:animated completion:completion];
} else {
[self dismissVisibleViewControllerToDirection:direction animated:animated completion:completion];
Expand Down Expand Up @@ -324,36 +326,67 @@ - (void)dismissVisibleViewControllerToDirection:(CNDirection)direction
[super dismissViewControllerAnimated:animated completion:completion];
}

// this method is quite tricky
//
- (void)dismissInvisibleViewControllerToDirection:(CNDirection)direction
animated:(BOOL)animated
completion:(void (^)(void))completion
{
// params
NSMutableDictionary *params = [NSMutableDictionary new];
params[@"animated"] = @(animated);

if (completion) {
params[@"completion"] = completion;
}
// - Now let's do some magic!

// visible view controller
// a visible view controller
CNViewController *visibleViewController = (CNViewController *)[self visibleViewController];

// do some magic
// freeze UI (we need this to avoid a blinking during further operations)
UIView *frozenView = [self freezeUI];

// dismiss all subsequent view controllers in a stack
[self dismissVisibleViewControllerToDirection:CNDirectionNone animated:NO completion:^{

// present a previously visible view controller
[self presentViewController:visibleViewController direction:CNDirectionGetOpposite(direction) animated:NO completion:^{

[visibleViewController performSelector:@selector(dismissWithParams:) withObject:params afterDelay:0.0f];
// at this point a receiver is followed by the visible view controller (all intermediate view controllers are removed, if had existed)

// unfreeze UI
[frozenView removeFromSuperview];

// dismiss params
NSDictionary *dismissParams = [self createParamsForDismissAnimated:animated completion:completion];

// make a common dismiss
[visibleViewController performSelector:@selector(dismissWithParams:) withObject:dismissParams afterDelay:0.0f];
}];
}];
}

- (UIView *)freezeUI
{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[self imageWithView:window]];
imageView.frame = window.bounds;
[window addSubview:imageView];
return imageView;
}

- (void)dismissWithParams:(NSDictionary *)params
{
[self dismissViewControllerAnimated:[params[@"animated"] boolValue] completion:params[@"completion"]];
}

- (NSDictionary *)createParamsForDismissAnimated:(BOOL)animated completion:(void (^)(void))completion
{
// params
NSMutableDictionary *params = [NSMutableDictionary new];
params[@"animated"] = @(animated);

if (completion) {
params[@"completion"] = completion;
}

return params;
}

- (UIViewController *)visibleViewController
{
UIViewController *viewController = self;
Expand Down Expand Up @@ -455,4 +488,16 @@ - (NSString *)storyboardIDForPanDirection:(CNDirection)direction
}
}

- (UIImage *)imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);

[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return image;
}

@end
2 changes: 1 addition & 1 deletion Demo/CrossNavigationDemo/LastViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ @implementation LastViewController
- (IBAction)restartDidPress:(id)sender
{
CNViewController *firstViewController = (CNViewController *)self.presentingViewController.presentingViewController;
[firstViewController dismissViewControllerToDirection:CNDirectionTop animated:YES completion:nil];
[firstViewController dismissViewControllerToDirection:CNDirectionLeft animated:YES completion:nil];
}

@end

0 comments on commit d3a48cc

Please sign in to comment.