0
votes

I would like to implement a custom interactive UIViewController transition that works as follows:

  • There is a parent UIViewController that presents a full-screen child UIViewController.
  • If I swipe left, the child view controller gets displaced to the left and a new child view controller appears on the right.
  • If the transition finishes, the new child view controller occupies the screen and the old child view controller is removed.

The interaction has to be interactive, so that the transition animation happens alongside the swipe gesture.

I have thought of two ways to implement this:

1) Use a UINavigationController and implement the UINavigationControllerDelegate protocol, setting up the animation and interaction controllers there.

However, this is not a good solution because I don't want stack-based navigation, and don't want to keep a reference to the old child view controller.

2) Implement the UIViewControllerTransitioningDelegate protocol and use the "presentViewController:animated:completion:" method.

However, this method should be used to present a view controller modally, not to replace a currently shown view controller with a new one.

Is there a different way to do this?

1

1 Answers

0
votes

You don't have to own multiple UIViewControllers to reach your target, also it's not recommended, and it'll cause you a lot of memory problems.

The best practice is to have a single UIViewController, and show the user a swiping effect, and change the view's data in the same time.

This code will give a cool swiping effect:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UISwipeGestureRecognizer *recognizerRight;
    recognizerRight.delegate = self;

    recognizerRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)];
    [recognizerRight setDirection:UISwipeGestureRecognizerDirectionRight];
    [self.view addGestureRecognizer:recognizerRight];


    UISwipeGestureRecognizer *recognizerLeft;
    recognizerLeft.delegate = self;
    recognizerLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeleft:)];
    [recognizerLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
    [self.view addGestureRecognizer:recognizerLeft];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)swipeleft:(UISwipeGestureRecognizer *)swipeGesture
{
    CATransition *animation = [CATransition animation];
    [animation setDelegate:self];
    [animation setType:kCATransitionPush];
    [animation setSubtype:kCATransitionFromRight];
    [animation setDuration:0.50];
    [animation setTimingFunction:
     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [self.view.layer addAnimation:animation forKey:kCATransition];

    [self changeViewContent];
}

-(void)swipeRight:(UISwipeGestureRecognizer *)swipeGesture
{
    CATransition *animation = [CATransition animation];
    [animation setDelegate:self];
    [animation setType:kCATransitionPush];
    [animation setSubtype:kCATransitionFromLeft];
    [animation setDuration:0.40];
    [animation setTimingFunction:
     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [self.view.layer addAnimation:animation forKey:kCATransition];

    [self changeViewContent];
}

-(void)changeViewContent
{
    // change the view content here
}

Also, if the views you want to swap between them has a totally different UI, then you can use a UITableViewController and change the table cells with every swipe to have the output you want.

I hope that's helping you.