Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9244427
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T09:01:38+00:00 2026-06-18T09:01:38+00:00

This is both a question and a partial solution. *Sample project here: https://github.com/JosephLin/TransitionTest Problem

  • 0

This is both a question and a partial solution.


*Sample project here:

https://github.com/JosephLin/TransitionTest


Problem 1:

When using transitionFromViewController:..., layouts done by the toViewController‘s viewWillAppear: doesn’t show up when the transition animation begins. In other words, the pre-layout view shows during the animation, and it’s contents snap to the post-layout positions after the animation.

Problem 2:

If I customize the background of my navbar’s UIBarButtonItem, the bar button shows up with the wrong size/position before the animation, and snaps to the correct size/position when the animation ends, similar to Problem 1.


To demonstrate the problem, I made a bare-bone custom container controller that does some custom view transitions. It’s pretty much a UINavigationController copy that does cross-dissolve instead of push animation between views.

The ‘Push’ method looks like this:

- (void)pushController:(UIViewController *)toViewController
{
    UIViewController *fromViewController = [self.childViewControllers lastObject];

    [self addChildViewController:toViewController];
    toViewController.view.frame = self.view.bounds;

    NSLog(@"Before transitionFromViewController:");
    [self transitionFromViewController:fromViewController
                      toViewController:toViewController
                              duration:0.5
                               options:UIViewAnimationOptionTransitionCrossDissolve
                            animations:^{}
                            completion:^(BOOL finished) {
                                [toViewController didMoveToParentViewController:self];
                            }];
}

Now, DetailViewController (the view controller I’m pushing to) needs to layout its content in viewWillAppear:. It can’t do it in viewDidLoad because it wouldn’t have the correct frame at that time.

For demonstration purpose, DetailViewController sets its label to different locations and colors in viewDidLoad, viewWillAppear, and viewDidAppear:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%s", __PRETTY_FUNCTION__);
    CGRect rect = self.descriptionLabel.frame;
    rect.origin.y = 50;
    self.descriptionLabel.frame = rect;
    self.descriptionLabel.text = @"viewDidLoad";
    self.descriptionLabel.backgroundColor = [UIColor redColor];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    NSLog(@"%s", __PRETTY_FUNCTION__);
    CGRect rect = self.descriptionLabel.frame;
    rect.origin.y = 200;
    self.descriptionLabel.frame = rect;
    self.descriptionLabel.text = @"viewWillAppear";
    self.descriptionLabel.backgroundColor = [UIColor yellowColor];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    NSLog(@"%s", __PRETTY_FUNCTION__);
    CGRect rect = self.descriptionLabel.frame;
    rect.origin.y = 350;
    self.descriptionLabel.frame = rect;
    self.descriptionLabel.text = @"viewDidAppear";
    self.descriptionLabel.backgroundColor = [UIColor greenColor];
}

Now, when pushing the DetailViewController, I’m expecting to see the label at y =200 at the begining of the animation (left image), and then jumps to y = 350 after the animation is finished (right image).

enter image description here enter image description here
Expected view before and after animation.


However, the label was at y=50, as if the layout made in viewWillAppear didn’t make it before the animation took place (left image). But notice that the label’s background was set to yellow (the color specified by viewWillAppear)!

enter image description here enter image description here
Wrong layout at the beginning of the animation. Notice that the bar buttons also start with the wrong position/size.


Console Log
TransitionTest[49795:c07] -[DetailViewController viewDidLoad]
TransitionTest[49795:c07] Before transitionFromViewController:
TransitionTest[49795:c07] -[DetailViewController viewWillAppear:]
TransitionTest[49795:c07] -[DetailViewController viewWillLayoutSubviews]
TransitionTest[49795:c07] -[DetailViewController viewDidLayoutSubviews]
TransitionTest[49795:c07] -[DetailViewController viewDidAppear:]
Notice that viewWillAppear: was called AFTER transitionFromViewController:


Solution for Problem 1

Alright, here comes the partial solution part. By explicitly calling beginAppearanceTransition: and endAppearanceTransition to toViewController, the view will have the correct layout before the transition animation takes place:

- (void)pushController:(UIViewController *)toViewController
{
    UIViewController *fromViewController = [self.childViewControllers lastObject];

    [self addChildViewController:toViewController];
    toViewController.view.frame = self.view.bounds;

    [toViewController beginAppearanceTransition:YES animated:NO];

    NSLog(@"Before transitionFromViewController:");
    [self transitionFromViewController:fromViewController
                      toViewController:toViewController
                              duration:0.5
                               options:UIViewAnimationOptionTransitionCrossDissolve
                            animations:^{}
                            completion:^(BOOL finished) {
                                [toViewController didMoveToParentViewController:self];
                                [toViewController endAppearanceTransition];
                            }];
}

Notice that viewWillAppear: is now called BEFORE transitionFromViewController:
TransitionTest[18398:c07] -[DetailViewController viewDidLoad]
TransitionTest[18398:c07] -[DetailViewController viewWillAppear:]
TransitionTest[18398:c07] Before transitionFromViewController:
TransitionTest[18398:c07] -[DetailViewController viewWillLayoutSubviews]
TransitionTest[18398:c07] -[DetailViewController viewDidLayoutSubviews]
TransitionTest[18398:c07] -[DetailViewController viewDidAppear:]


But that doesn’t fix Problem 2!

For whatever reason, the navbar buttons still begin with the wrong position/size at the beginning of the transition animation. I spent so many time trying to find THE right solution but without luck. I’m starting to feel it’s a bug in transitionFromViewController: or UIAppearance or whatever. Please, any insight you can offer to this question is greatly appreciated. Thanks!


Other solutions I’ve tried

  • Call [self.view addSubview:toViewController.view]; before transitionFromViewController:

It actually gives exactly the right result to the user, fixes both Problem 1&2. The problem is, viewWillAppear and viewDidAppear will both be called twice! It’s problematic if I want to do some expansive animation or calculation in viewDidAppear.

  • Call [toViewController viewWillAppear:YES]; before transitionFromViewController:

I think it’s pretty much the same as calling beginAppearanceTransition:. It fixes Problem 1 but not Problem 2. Plus, the doc says not to call viewWillAppear directly!

  • Use [UIView animateWithDuration:] instead of transitionFromViewController:

Like this:
[self addChildViewController:toViewController];
[self.view addSubview:toViewController.view];
toViewController.view.alpha = 0.0;

[UIView animateWithDuration:0.5 animations:^{
    toViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
    [toViewController didMoveToParentViewController:self];
}];

It fixes Problem 2, but the view started with the layout in viewDidAppear (label is green, y=350). Also, the cross-dissolve is not as good as using UIViewAnimationOptionTransitionCrossDissolve

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T09:01:40+00:00Added an answer on June 18, 2026 at 9:01 am

    Ok, adding layoutIfNeeded to the toViewController.view seems to do the trick – this gets the view laid out properly before it shows up on screen (without the add/remove), and no more weird double viewDidAppear: call.

    - (void)pushController:(UIViewController *)toViewController
    {
        UIViewController *fromViewController = [self.childViewControllers lastObject];
    
        [self addChildViewController:toViewController];
    
        toViewController.view.frame = self.view.bounds;
        [toViewController.view layoutIfNeeded];
    
        NSLog(@"Before transitionFromViewController:");
        [self transitionFromViewController:fromViewController
                          toViewController:toViewController
                                  duration:0.5
                                   options:UIViewAnimationOptionTransitionCrossDissolve
                                animations:^{}
                                completion:^(BOOL finished) {
                                }];
    
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've done some research on this question (both via google and on here), but
This is kind of a COM question to do with DirectX. So, both ID3DXSprite
This question is for the people who know both Haskell (or any other functional
This is kind of a two part question. But it both relates to the
I believe this question applies equally well to C# as to Java, because both
I read this question here: Is there a way to override the empty constructor
I know this question has been asked many times here, but no answer has
I have a problem (obviously the question :) I have a project-- MyProject... hence
Another collinear-points question. This one's twist is, I'm using integer arithmetic, and I'm looking
I have a pattern to process web service requests using chained partial functions (this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.