views:

5727

answers:

4

I have a View that has a UIWebView, and an OptionsPane (Custom UIViewController with Custom view).

I want when the view is shown, for the options pane (located on the top of the main view) to FLIP into place. I am using the code, and I am getting a strange result.

The FIRST time the view is shown, the options pane seems to already be visible... When I hit BACK on my navController, and pull up the View again, the animation works perfectly.

Can anyone shed some light on this topic?

- (void)viewDidLoad {
    [super viewDidLoad];
    optionsPane=[[OptionsPaneController alloc] initWithNibName:@"OptionsPane" bundle:nil];
}

- (void)viewWillAppear:(BOOL)animated {

    [optionsPane.view removeFromSuperview];
    [self checkOptionsVisible];
}

-(void)checkOptionsVisible{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.5]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[optionsPane view] cache:YES];
    [[self view] addSubview:[optionsPane view]];
    [theWebView setFrame:CGRectMake(0,87,320,230)];
    [[optionsPane view] setFrame:CGRectMake(0,0,320,87)];
    [UIView commitAnimations];   
}
+1  A: 

Hmm, I don't think the viewWillAppear message is getting sent the first time. There are two things that I read in the SDK. You should call super inside that message and there is a big warning that may apply to your first time:

Warning: If the view belonging to a view controller is added to a view hierarchy directly, the view controller will not receive this message. If you insert or add a view to the view hierarchy, and it has a view controller, you should send the associated view controller this message directly. Failing to send the view controller this message will prevent any associated animation from being displayed.

Ultimately, I would run through the debugger and make sure that viewWillAppear message is being sent when you think it is.

Boiler Bill
Very interesting... I must have missed that note. Let me play around with it a bit and let you know what the story is as I do BELIEVE it is being called.
Dutchie432
It's firing the first time, alright - as well as all of the subsequent times.
Dutchie432
bummer, I was hoping that would help
Boiler Bill
A: 

Updated for your situation:

Instead have four views:

  1. A backing view

  2. The main View

  3. The back view (options pane) 100 pixels

  4. The front view (blank view) 100 pixels

Add the main view to the backing view as normal.

Add the front view to the backing view where you would like the options pane to appear.

make sure the front and back view have the same frame.

Use the same code as below using the methods flip the front and back views.


Original Answer

You need 3 views:

  1. A backing view

  2. The front View

  3. The back view

The backing view just holds the other 2 as they flip back and forth Below are the flipping methods. I place them both in backingViewController:

- (void)displayBack{

    //parent controller is an ivar so the sub-view controllers know who their daddy is
    backController.parentController = self;


    [UIView beginAnimations:nil context:@"flipTransitionToBack"];
    [UIView setAnimationDuration:1.2];

    //note self.view IS the backing view
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];

    //remove the front view
    [[frontController view] removeFromSuperview];
    //add the back view view
    [self.view addSubview:[backController view]];
    [UIView commitAnimations];

    //giving a heads up to the view that is about to come on screen
    [backController viewWillAppear:YES];

}



- (void)displayFront{

    [UIView beginAnimations:nil context:@"flipTransitionToFront"];
    [UIView setAnimationDuration:1.2];

    [UIView setAnimationDelegate:self];

    //I'm interested in knowing this has happened
    [UIView setAnimationDidStopSelector:@selector(flipAnimationDidEndWithID:finished:context:)];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
    //remove back view
    [[backController view] removeFromSuperview];
    //add the front view
    [self.view addSubview:[frontController view]];
    [UIView commitAnimations];

}
Corey Floyd
The difference is that I have BOTH views displaying at the same time, one that is about 100 pixels high directly above the other - and I am not switching between them - I am just having the top view "appear" in a flipping manner.
Dutchie432
hmm... then just make a "fake" front view that is blank and also 100 pixels high. Switch between that and the option pane. That should solve your issue.
Corey Floyd
I'm going to need to try this in a separate project before 'ripping apart' my current code to see if this works. I will keep you posted.
Dutchie432
Good luck. For encouragement, this snippet absolutely DOES work in a production project. Whether it will work with just a partial subview, you'll find out when you test it.
Corey Floyd
Im really not sure I need to do all of this... After studying this code in preparation to implement it - this code really transitions between two UIViews.. I am trying to have a UIView show as an object on another UIView, if you will... Let me know if I'm missing something...
Dutchie432
A: 

Hi,

If I understand what your explaining, I had a very similar problem the other day.

What happening on the first load is that viewDidLoad fires first. loading the nib file takes a bit more time than it takes for the viewWillAppear to fire itself.

What we're getting is a nib loads after the viewWillApper already retired.

On any load after that, the viewDidLoad will not fire, letting the viewWillAppear to do its loyal flipping job.

What to do?
First, try to change your code to use "viewDidAppear". That should help, but you have to see if it looks good.

Another option (ugly one, I know) is to have a call to checkOptionsVisible on the viewDidLoad too.
If non of that help, I would consider a timer as a hack - if the requirements allow it.

I hope that make you closer to solve the problem.

yn2
Interesting... moving the function call to viewDidAppear causes some really funky effects, and not quite what I'm trying to do... I will need to play around with the timer option and get back to you. Thanks!
Dutchie432
Thanks for commenting it out. I'm looking forward to hear what worked for you (and probably work for me too in the end :) ).
yn2
A: 

The view property on a UIViewController is lazily-loaded -- even when you're init-ing with a nib as you are here, the view itself doesn't actually get instantiated until the first time the property is accessed.

It's hard to know exactly what's happening without seeing more code, but you may get the results you want if you access optionsPane.view in viewDidLoad (you don't need to do anything with it, just access the property to force loading).

Skirwan
I tried doing something like NSLog(@"%d",optionsPane.view.bounds.size.height); immediately after I set optionsPane=[[optionsPane alloc] init]; these get called before the optionsPane view is added as a subview. Still to no avail. I am starting to wonder if I should just scrap the animation - it really is non essential.
Dutchie432
Okay, so much for that idea... Here's a new one: The only thing that's different the second time through is that [optionsPane.view removeFromSuperview] is actually doing something. Have you tried adding the optionsPane.view to self.view in viewDidLoad? It's possible that the no-op removeFromSuperview is somehow preventing the animation system from recognizing that the subsequent addSubview is animatable.
Skirwan
I do believe I previously tried that. I implements that line again and there is no visible change whatsoever... I appreciate your efforts!
Dutchie432
typo - Implemented*
Dutchie432
Here is a strange piece of information. If, in the viewDidLoad, I set [[optionsPane view] setFrame:CGRectMake(0,0,0,0)]; - the animation of the change from (0,0,0,0) to the (0,0,320,87) specified in checkOptionsVisible is shown. So - why would THAT animate, and not the 'problem' animation?
Dutchie432
Oh, and on the second run-through the resize animation does NOT show, while the 'problem' animation does.
Dutchie432