0

I'm implementing a custom segue with zooming animations between A view and B view. My thought is described as below.

When segue goes from A to B:

  1. Save a snapshot image of the B view, add this image view into A view as A's subview

  2. Perform zoom-in animation of the fake image view (it acts like the B view goes larger and larger until it fills the entire screen)

  3. When the zoom-in animation completes, push the real B view with no animation using navigation controller and remove the fake image view from A view

When segue goes from B to A (unwind):

  1. Save a snapshot image of B view, add it into A view as A's subview and bring it to front

  2. Pop B view with no animation using navigation controller

  3. Perform zooming-out animation of the fake image view (it acts like the B view goes smaller and smaller until it is too small to see)

It works fine in A to B case, while in B to A case, after step 2, the real B view should be gone and there is a fake image view of B on top of A view. Here comes the problem, if the fake image view of B was not removed from the A view's subviews after step 3, when A view appears, B should still exists in A's subviews but it seems this subview was gone.

I have found a same problem here: View transition doesn't animate during custom pop segue but nobody was answering it.

So, anyone any ideas?

1 Answer 1

1

I'm not sure, but I don't think you should be adding views to A when coming from B, the problem might be there. Instead add both views on B.

This code works:

    //ZoomInSegue.m
    - (void)perform {
        UIViewController* source = (UIViewController *)self.sourceViewController;
        UIViewController* destination = (UIViewController *)self.destinationViewController;

        //Custom method to create an UIImage from a UIView
        UIImageView * destView = [[UIImageView alloc] initWithImage:[self imageWithView:destination.view]];             

        CGRect destFrame = destView.frame;
        destFrame.origin.x = destination.view.frame.size.width/2;
        destFrame.origin.y = destination.view.frame.size.height/2;
        destFrame.size.width = 0;
        destFrame.size.height = 0;
        destView.frame = destFrame;

        destFrame = source.view.frame;

        [source.view addSubview:destView];

        [UIView animateWithDuration:1.0
                         animations:^{
                             destView.frame = destFrame;
                         }
                         completion:^(BOOL finished) {
                             [destView removeFromSuperview];
                             [source.navigationController pushViewController:destination animated:NO];
                         }];
    }

    //ZoomOutSegue.m
    - (void)perform {
        UIViewController* source = (UIViewController *)self.sourceViewController;
        UIViewController* destination = (UIViewController *)self.destinationViewController;

        //Custom method to create an UIImage from a UIView
        UIImageView* sourceView = [[UIImageView alloc] initWithImage:[self imageWithView:source.view]]; 

        CGRect sourceFrame = sourceView.frame;
        sourceFrame.origin.x = source.view.frame.size.width/2;
        sourceFrame.origin.y = source.view.frame.size.height/2;
        sourceFrame.size.width = 0;
        sourceFrame.size.height = 0;

        [source.view addSubview:destination.view];
        [source.view addSubview:sourceView];

        [UIView animateWithDuration:1.0
                         animations:^{
                             sourceView.frame = sourceFrame;
                         }
                         completion:^(BOOL finished) {
                             [source.navigationController popViewControllerAnimated:NO];
                         }];
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot @Odrakir, your advice works. I have done some more trial, it seems that in custom segue, the popped controller instance was not the same one with segue's destination controller instance. This may explains why changes to destination view in segue has gone when it finally shows on screen after popped, but the mechanism behind segue and navigation controller is still confused to me: why segue needs to instantiate a new destination controller but it keeps the destination view's status when the view was popped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.