UIView transitionWithView doesn't work
Asked Answered
S

2

8

Here is viewDidLoad from the main view controller in the test project:

- (void)viewDidLoad

{ [super viewDidLoad];

UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 300, 300)];
[self.view addSubview:containerView];

UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
[redView setBackgroundColor:[UIColor redColor]];
[containerView addSubview:redView];

UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
[yellowView setBackgroundColor:[UIColor yellowColor]];


[UIView transitionWithView:containerView duration:3
                   options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
                       [redView removeFromSuperview];
                       [containerView addSubview:yellowView];
                   }
                completion:NULL];
}

The yellow box just appears. There is no animation, no matter which UIViewAnimationOption I try. Why???

EDIT: I've also tried using performSelector withDelay to move the animation out of viewDidLoad and into another method. Same result - no animation.

Also tried this: [UIView transitionFromView:redView toView:yellowView duration:3 options:UIViewAnimationOptionTransitionFlipFromLeft completion:NULL];

Still, the yellow view just appears. No animation.

Syrinx answered 30/9, 2011 at 22:21 Comment(0)
L
6

After some testing it appears that you cannot create the container view and set up the animation within the same runloop and have things work. In order to make your code work, I first created the containerView and the redView in the viewDidLoad method. Then I put your animation into the viewDidAppear method. So that I could reference the containerView and the redView from the viewDidAppear method, I made them properties. Here is the code for an ST_ViewController.m file that will perform the animation you wanted.

@interface ST_ViewController ()
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIView *redView;
@end

@implementation ST_ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setContainerView:[[UIView alloc] initWithFrame:CGRectMake(10, 10, 300, 300)]];
    [[self view] addSubview:[self containerView]];

    [self setRedView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)]];
    [[self redView] setBackgroundColor:[UIColor redColor]];
    [[self containerView] addSubview:[self redView]];
}

-(void)viewDidAppear:(BOOL)animated{

    [super viewDidAppear:animated];



    UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
    [yellowView setBackgroundColor:[UIColor yellowColor]];


    [UIView transitionWithView:[self containerView]
                      duration:3
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^(void){
                        [[self redView] removeFromSuperview];
                        [[self containerView] addSubview:yellowView];
                         }

                    completion:nil];

}

@end
Leiva answered 18/10, 2012 at 17:52 Comment(3)
I've come to the same conclusion, but I was wondering why that is? Any ideas?Cyprus
Look at Kenny's answer below. There are things that aren't totally set up until viewDidAppear.Leiva
Nah, that doesn't have to do with it. I was talking in the general sense if you're adding a view and then doing the animation, after the view has loaded. I've figured it out, though, more info here - andrewmarinov.com/working-with-uiviews-transition-animationsCyprus
U
2

Don't put this in viewDidLoad. viewDidLoad is called when the view is fully loaded into memory, but not yet displayed on screen.

Try putting the above code in viewDidAppear: which is called when the view has appeared on screen.

Edit: a side note, if performSelector:withDelay: fixes something, that means you're trying to do that thing wrong. You need to refactor somehow. performSelector:withDelay: is the wrong way to solve problems 99.999% of the time. As soon as you place this code on a different speed device (new iPhone, old iPhone) it will mess up.

Umbrella answered 1/10, 2011 at 0:49 Comment(3)
Moving it to viewDidAppear has no effect. Still, the yellow view just appears with no animation.Syrinx
Your "side note" statement just isn't true. Some things, especially many things in UIKit, just need to happen the next time through the run loop so the OS can have a chance to draw them. Using -performSelector:withObject:afterDelay is a fine way to give the OS a chance to update a view before you animate it, render it in a context, etc. A delay of 0.0 is enough to get it on the next run loop pass. It won't mess up timing depending on device.Embarrass
@DaveBatton it's always a code smell for me, but you're right that's an opinion not a fact. It may not be wrong per se, but there is always a cleaner way to do things (99.999% of the time, anyway).Umbrella

© 2022 - 2024 — McMap. All rights reserved.