View Controllers: How to switch between views programmatically? - iphone

In short: I want to have two fullscreen views, where I can switch between view A and view B. I know I could just use an Tab Bar Controller, but I dont want to. I want to see how this is done by hand, for learning what's going on under the hood.
I have an UIViewController that acts as an root controller:
#interface MyRootController : UIViewController {
IBOutlet UIView *contentView;
}
#property(nonatomic, retain) UIView *contentView;
#end
The contentView is hooked up to an UIView which I added as an subview to the "view" of the Nib. This has green color and I see it fullscreen. Works fine.
Then, I created two other View Controllers pretty much the same way. ViewControllerA and ViewControllerB. ViewControllerA has a blue background, ViewControllerB has a black background. Just to see which one is active.
So, in the implementation of myRootController, I do this:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
ViewControllerA *vcA = [[ViewControllerA alloc] initWithNib];
[self.contentView addSubview:vcA.view];
[cvA release];
}
By the way, the -initWithNib method looks like this:
- (id)initWithNib { // Load the view nib
if (self = [super initWithNibName:#"ViewA" bundle:nil]) {
// do ivar initialization here, if needed
}
return self;
}
That works. I see the view from ViewControllerA when I start the app. But now the big question is: A View Controller typically has all those methods like:
(void)viewWillAppear:(BOOL)animated;
(void)viewDidDisappear:(BOOL)animated;
(void)viewDidLoad;
...and so on. Who or what, or how would those methods be called if I do it "my" way without a tab bar controller? I mean: If I allocate that ViewController's class and the view get's visible, would I have to take care about calling those methods? How does it know that viewWillAppear, viewDidDisappear, or viewDidLoad? I believe that the Tab Bar Controller has all this "cleverness" under the hood. Or am I wrong?
UPDATE: I've tested it. If I release the view controller (for example: ViewControllerA), I will get no log message on viewDidDisappear. Only when allocating and initializing the ViewControllerA, I get an viewDidLoad. But that's it. So all signs stand for the cleverness of UITabBarController now ;) and I have to figure out how to replicate that, right?

There's a nice example of switching views in Chapter 6 of Beginning iPhone Development. You can see the source code for it here:
http://iphonedevbook.com/
SwitchViewController has the code to change views programatically.
- (IBAction)switchViews:(id)sender
{
if (self.yellowViewController == nil)
{
YellowViewController *yellowController = [[YellowViewController alloc]
initWithNibName:#"YellowView" bundle:nil];
self.yellowViewController = yellowController;
[yellowController release];
}
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
if (self.blueViewController.view.superview == nil)
{
coming = blueViewController;
going = yellowViewController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else
{
coming = yellowViewController;
going = blueViewController;
transition = UIViewAnimationTransitionFlipFromRight;
}
[UIView setAnimationTransition: transition forView:self.view cache:YES];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[going.view removeFromSuperview];
[self.view insertSubview: coming.view atIndex:0];
[going viewDidDisappear:YES];
[coming viewDidAppear:YES];
[UIView commitAnimations];
}

You can begin from the simplest removeFromSuperview/insertSubview and add code to it little by little.
//SwitchViewController.h
#import
#class BlueViewController;
#class YellowViewController;
#interface SwitchViewController : UIViewController {
IBOutlet BlueViewController *blueViewController;
IBOutlet YellowViewController *yellowViewController;
}
- (IBAction)switchViews:(id)sender;
#property (nonatomic, retain) BlueViewController *blueViewController;
#property (nonatomic, retain) YellowViewController *yellowViewController;
#end
//1. remove yellow view and insert blue view
- (IBAction)switchViews:(id)sender {
if(self.blueViewController.view.superview == nil)
{
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];
}
}
//2. appear=insert, disappear=remove
if(blueViewController.view.superview == nil)
{
[blueViewController viewWillAppear:YES];
[yellowViewController viewWillDisappear:YES];
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:self.blueViewController.view atIndex:0];
[yellowViewController viewDidDisappear:YES];
[blueViewController viewDidAppear:YES];
}
//3. now add animation
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
//blue view will appear by flipping from right
if(blueViewController.view.superview == nil)
{
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight
forView:self.view cache:YES];
[blueViewController viewWillAppear:YES];
[yellowViewController viewWillDisappear:YES];
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:self.blueViewController.view atIndex:0];
[yellowViewController viewDidDisappear:YES];
[blueViewController viewDidAppear:YES];
}
[UIView commitAnimations];

If I understand correctly, what you are trying to accomplish is pretty straightforward.
Just add a UINavigationController on your application delegate and do:
[navigationController pushView:vcA];
Delegates will be called accordingly:
(void)viewWillAppear:(BOOL)animated;
(void)viewDidDisappear:(BOOL)animated;
(void)viewDidLoad;
And when you want to pop the view and push another one:
[navigationController popViewControllerAnimated:true];
[navigationController pushView:vcB];
If you don't want the navigationController showing just use:
[navigationBar setHidden:YES];
Where navigationBar is the UINavigationBar corresponding to your UINavigationController.

This may be an old issue, but I recently came across the same problem and had a hard time finding something that worked. I wanted to switch between two complementary view controllers, but I wanted the switch to be animated (built in animations work fine), and I wanted it to be compatible with storyboards if possible.
For taking advantage of built-in transition, UIView's +transitionFromView:toView:duration:options:completion: method works beautifully. But, it only transitions between views, not view controllers.
For the transition to be between whole view controllers, not just views, creating a custom UIStoryboardSegue is the way to go. Whether or not you use storyboards, this approach lets you encapsulate the whole transition and manage the passing of relevant information from one view controller to the next. It only involves subclassing UIStoryboardSegue and overriding a single method, -perform.
For a reference implementation, see RAFlipReplaceSegue, the exact custom segue I put together using this approach. As a bonus, it also replaces the old view controller with the new if it is in a UINavigationController stack.

Related

Embedding two UITableViewControllers in one UIViewController

I have a design where I need to swap in and out two tableviews using one viewcontroller (I need the same navigation title to appear for both). So I've created each tableview in its own subclassed tableviewcontroller class, then I've included a class variable for each in my viewcontroller. Each tableview has the viewcontroller as a parent and calls the viewcontrollers swap method when a swap needs to occur. This method and the viewDidLoad method is listed below:
- (void) viewDidLoad
{
[super viewDidLoad];
[[self navigationItem] setTitle: AddAPhotoViewControllerTitle];
SelectAnAlbumTableViewController *selectAnAlbumTableViewControllerTemp = [[SelectAnAlbumTableViewController alloc] initWithParent: self];
[self setSelectAnAlbumTableViewController: selectAnAlbumTableViewControllerTemp];
[selectAnAlbumTableViewControllerTemp release];
[[self view] insertSubview: [[self selectAnAlbumTableViewController] tableView] atIndex: 0];
}
- (void) switchTableViews
{
if ([[[self selectAnAlbumTableViewController] tableView] superview] == nil)
{
[[self view] insertSubview: [[self selectAnAlbumTableViewController] tableView] atIndex: 0];
[[[self selectAPhotoTableViewController] tableView] removeFromSuperview];
[selectAPhotoTableViewController release];
selectAPhotoTableViewController = nil;
}
else
{
SelectAPhotoTableViewController *selectAPhotoTableViewControllerTemp = [[SelectAPhotoTableViewController alloc] initWithAssetGroup: [[self selectAnAlbumTableViewController] assetGroup] parent: self];
[self setSelectAPhotoTableViewController: selectAPhotoTableViewControllerTemp];
[selectAPhotoTableViewControllerTemp release];
[[self view] insertSubview: [[self selectAPhotoTableViewController] tableView] atIndex: 0];
[[[self selectAnAlbumTableViewController] tableView] removeFromSuperview];
}
I have 2 questions:
1) When I'm doing the swap, I'm inserting the new tableview, animating the transition (I didn't include the animation code to keep it concise), then removing the old tableview from the superview. Is this the correct order / correct way to do this? It works fine, but I'm wondering if there isn't some code smell here.
2) Using this design pattern, what would be the best way to go about putting in an activity indicator that can be displayed while each tableview is loading? I've tried implementing the indicator in the viewcontroller, and it seemed to work ok, but I wasn't sure how to set it's position? In terms of what? The center of? I guess this goes back to the first question I asked to, what is the superview and when, or if there is even a superview?
Just use two UITableViews.
Instantiate them and put them in instance variables. If you need to, save the state i.e. which table view is being displayed.
I see nothing wrong with it. I assume your reason is that each table controller has its own logic as to deserve a separate class. It is a bit unorthodox to embed controllers inside controllers, and you'll have to pass the view lifecycle calls.
Example:
-(void) switch
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDelegate:self];
if ([self.visibleVC isKindOfClass:[OrangeVC class]])
{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[self.visibleVC viewWillDisappear:TRUE];
[self.visibleVC.view removeFromSuperview];
self.visibleVC = self.appleVC;
[self.view addSubview:self.visibleVC.view];
}
else if ([self.visibleVC isKindOfClass:[AppleVC class]])
{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.visibleVC viewWillDisappear:TRUE];
[self.visibleVC.view removeFromSuperview];
self.visibleVC = self.orangeVC;
[self.view addSubview:self.visibleVC.view];
}
[self.visibleVC viewWillAppear:TRUE];
[UIView commitAnimations];
}
Note the viewWillAppear calls, you need at least that to wake up the table. I'm not sure if you should call viewWillDisappear, but it doesn't hurt. If you don't, watch it in instruments in case the controller is not cleaning up properly.
You can add any activity hud in the self.view of the parent controller, use a hud widget, darken the view currently loading, ..., it's a design issue more than technical. Remember to disable the user interaction while you load (userInteractionEnabled=NO) on the parent view and the button that initiated the switch.

pushing a view when clicking on an annotation

I am trying to push a view when a user clicks on an annotation, I have the following code in place:
- (void) mapView: (MKMapView *) mapView annotationView:(MKAnnotationView *) view calloutAccessoryControlTapped:(UIControl *) control
{
childController = [[NeighborProfileViewController alloc] initWithNibName:#"NeighborProfileViewController" bundle:nil];
childController.title = view.annotation.title;
childController.uid = [((NeighborMapAnnotation *)(view.annotation)) uid];
[self.navigationController pushViewController:childController animated:YES];
}
I know that the code executes inside this fragment as I tried to print out something and it did print. However, why isn't it changing views to the view that I already push?
Is this because this view is actually a subView of the main view, which actually has the navigation controller? If this is the case, then how do I get around this. Here's the code that loads the subView:
-(IBAction) toggleAction:(id) sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
if(self.navigationItem.rightBarButtonItem.title == #"List"){
self.navigationItem.rightBarButtonItem.title = #"Map";
[mapViewController.view removeFromSuperview];
}else {
[self.view addSubview:mapViewController.view];
[self.view sendSubviewToBack:self.view];
self.navigationItem.rightBarButtonItem.title = #"List";
}
[UIView commitAnimations];
}
in other words the calloutAccessoryControlTapped is inside the mapViewController
Your code is insufficient to answer the following questions:
Is your navigation controller initialized?
Even though you are calling self.navigationController, if it is nil, then nothing will happen.
Is the xib name spelled correctly? If you push a controller onto the navigation stack with an incorrect xib name, an error may not be thrown and your controller will not be pushed onto the stack.
EDIT:
You need to create an instance of a UINavigationController before you show your initial view. Here is an example of presenting a modal view:
YourViewController* rootViewController; /* however you are creating the initial view */;
UINavigationController navController =
[[UINavigationController alloc] initWithRootViewController:rootViewController];
[rootViewController release];
[self presentModalViewController:navController animated:YES];
[navController release];
your mapviewcontroller doesn't have a reference to the navigationcontroller. your main view controller does. so what you need to do is pass the reference to your navigation controller onto the maview controller, and push the view onto that. Let me know if you have any questions

Hide subview of different view controller

I have a view that acts as a background (light grey 0.5 alpha) for for another custom alert view.
When the user taps my OK button on the custom alert, i want to hide the custom alert and the background view also.
Both views are subviews of the same superview...
I do this in the buttonTapped: method to hide the views, and it works for the first attempt, but from the second time onwards, the background views never dismiss... the alerts hide correctly every time.
[UIView animateWithDuration:0.5f animations:^{
self.view.alpha=0.0f; //hide alert
[self.view.superview viewWithTag:1].alpha=0.0f; //hide background
}];
They are added as subviews, as follows:
ResultDialogController *dialogController = [[[ResultDialogController alloc] initWithNibName:#"ResultDialogController_" bundle:nil] retain];
ResultBackgroundViewController *bgViewController = [[[ResultBackgroundViewController alloc] initWithNibName:#"ResultView" bundle:nil] retain];
dialogController.view.alpha=0;
bgViewController.view.alpha=0;
bgViewController.view.tag=1;
[UIView animateWithDuration:0.5f animations:^{
bgViewController.view.alpha=0.5f;
dialogController.view.alpha=1.0f;
}];
[self.view addSubview:bgViewController.view];
[self.view addSubview:dialogController.view];
[dialogController release];
[bgViewController release];
How can i always dismiss the background view?
Thanks
You don't seem to remove the views, you are just making the invisible by setting the alpha to zero. So every time you call your second code sample you will add a new version of the background view and the dialog view to self.view. At the second call you will have two background views, both with tag = 1 and you are getting your first background view from the call to [self.view.superview viewWithTag:1] which is why your newly added background view does not get invisible.
But that is not all, you also have a memory leak for ResultDialogController and ResultBackgroundViewController. The call to retain is not necessary when you are calling initWithNibName:bundle:. Perhaps you are doing this because you some crash when you released the controllers?
What you should do is to create ivars and properties for your controllers.
#property (nonatomic, retain) ResultDialogController *resultController;
#property (nonatomic, retain) ResultBackgroundController *backgroundController;
Then when showing the controllers you can do something like:
ResultDialogController *dialogController = [[ResultDialogController alloc] initWithNibName:#"ResultDialogController_" bundle:nil];
self.dialogController = dialogController;
ResultBackgroundViewController *bgViewController = [[ResultBackgroundViewController alloc] initWithNibName:#"ResultView" bundle:nil];
self.backgroundController = bgViewController;
// do the same as before
Then in buttonTapped: you do:
[UIView animateWithDuration:0.5f
animations: ^{
self.dialogController.view.alpha = 0;
self.backgroundController.view.alpha = 0;
}
completion: ^(BOOL finished){
[self.dialogController.view removeFromSuperview];
[self.backgroundController.view removeFromSuperview];
}
];
And to top it off, don't forget to release the controller ivars in dealloc.
You can hide them by setting HIDE property for the views to be true.

iPhone flip right button (like iTunes)

I'm trying to flip between two views. That's easy, the code is below, but I also want to simultaneously flip the button used to perform the flip.
You can see this behavior in the iPod application when you're playing a track; tapping the flip button flips between the cover art and the track listing, but it flips the button at the same time.
This is a page on the navigation controller, and the button I want to flip is the rightBarButtonItem.
Here's the code I have so far. This flips the view, but not the rightBarButton.
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: 0.5f];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
showingBackside = !showingBackside;
if (showingBackside) {
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft
forView: self.view
cache: YES];
[self.view addSubview: backside.view];
[frontside.view removeFromSuperview];
} else {
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight
forView: self.view
cache: YES];
[self.view addSubview: frontside.view];
[backside.view removeFromSuperview];
}
// flip image, too
NSString *newImage = showingBackside ? #"backside.png" : #"frontside.png";
[(self.navigationItem.rightBarButtonItem) setImage: [UIImage imageNamed: newImage]];
[UIView commitAnimations];
(The image flipping code here may not compile; I added it after to try to explain what I was trying to do.)
Where I'm running into trouble is I want to change the rightmost button in the navigation controller so it flips simultaneously.
How do I do this? What view do I animate, and do I do it as part of the same animation block or as a separate one? Any tips would be appreciated, I definitely don't have a good handle on animation yet.
There's some discussion here, but the solution is not so elegant.
First of all, since UIBarButtonItem is not a descendant of UIView, you probably cannot use UIKit animations directly on the UIBarButtonItem. However, you can try setting a customView and animating that. You can use the same animation block.
Okay, here's what I actually did to fix this:
I was already using a custom title view. Instead of using rightBarButtonItem, I made my custom view wider.
I created an image of both sides of the button, complete with the navigation frame, and embedded them into the application. In my title view, I put:
A UIView that will be my replacement for the right control (call it rightControl), positioned appropriately.
A button over the UIView that responds to UIControlEventTouchUpInside and triggers my flipSide:.
At runtime I create a UIImageView for each state. I putboth UIImageViews in rightControl, but hide the one that isn't default. I switch the hidden flags around in flipSide: in a dedicated animation block.
Insanely weird. But it works.
Just use a custom UIView for the right navigation button that contains two buttons to flip between.
You can use a straight forward approach of creating a custom UIView that is displayed as the right navigation button item. This UIView should contain the two UIButtons you want to flip between. Remember that UIButtons are UIViews too so they can be flipped using the same transitions that a normal UI view can be flipped with and of course they can be tapped! Here is some sample code that works:
Note: I use a convenience function to create buttons as a custom category of UIViewController (note: you can add this same code to create a custom category for UIView too, just copy the same lines and replace UIViewController with UIView) - If you want to use it too just create a custom category by including this code below, alternately you can create the UIButtons as you normally would.
// create custom category for UIViewController to allow common button creation routine, add to .m or .mm file or add to a .h file and #import that .h file
#interface UIViewController (ButtonAndSelector)
- (UIButton *)createUIButtonWithImage:(UIImage *)image forState:(UIControlState)state withSelector:(SEL)selector usingFrame:(CGRect)buttonImageFrame;
#end
#implementation UIViewController (ButtonAndSelector)
- (UIButton *)createUIButtonWithImage:(UIImage *)buttonImage forState:(UIControlState)state withSelector:(SEL)selector usingFrame:(CGRect)buttonImageFrame
{
UIButton *button = [[UIButton alloc] initWithFrame:buttonImageFrame];
[button setBackgroundImage:buttonImage forState:state];
[button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
[button setShowsTouchWhenHighlighted:YES];
return button;
}
#end
// add this to your .h file:
#property (strong, nonatomic) UIView *coverListView;
#property (strong, nonatomic) UIButton *listButton;
#property (strong, nonatomic) UIButton *coverButton;
- (void)animateCoverListButtonFlip;
// add this to your .m or .mm file to synthesize the variables:
#synthesize coverListView;
#synthesize listButton;
#synthesize coverButton;
// add this to your .m or .mm file in the viewDidLoad:
// setup right button bar (flips between list icon and coverart image)
self.coverListView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 30)];
self.coverListView.backgroundColor = [UIColor clearColor];
self.coverListView.opaque = NO;
self.listButton = [self createUIButtonWithImage:[UIImage imageNamed:#"navbar_icon_tracklisting"] forState:UIControlStateNormal withSelector:#selector(showHideQueue) usingFrame:CGRectMake(0, 0, 32, 30)];
self.listButton.backgroundColor = [UIColor clearColor];
self.listButton.showsTouchWhenHighlighted = NO;
self.coverButton = [self createUIButtonWithImage:[UIImage imageNamed:#"default_coverart_small"] forState:UIControlStateNormal withSelector:#selector(showHideQueue) usingFrame:CGRectMake(0, 0, 32, 30)];
[self.coverListView addSubview:self.coverButton]; // show coverButton by default
self.coverButton.showsTouchWhenHighlighted = NO;
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.coverListView];
[self.navigationItem setRightBarButtonItem:barButtonItem];
// add this to viewDidAppear if you want to flip the button when the screen appears like the build in iPod app does
[self animateCoverListButtonFlip];
// add this routine to flip the right navigation bar custom view / buttons
- (void)animateCoverListButtonFlip
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:([self.listButton superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.coverListView cache:YES];
if ([self.listButton superview]) {
[self.listButton removeFromSuperview];
[self.coverListView addSubview:self.coverButton];
} else {
[self.coverButton removeFromSuperview];
[self.coverListView addSubview:self.listButton];
}
[UIView commitAnimations];
}
// when the playing album cover changes, remember to update the coverButton:
UIImage *artworkImage; // set this to the current playing album image
[self.coverButton setImage:artworkImage forState:UIControlStateNormal];
// don't forget to call the animateCoverListButtonFlip in the button click handler (shown above as showHideQueue) that shows and hides the cover/queue(list of album tracks0 - something like this:
- (void)showHideQueue
{
[self animateCoverListButtonFlip];
/* replace the code below that is commented out here with your own code that transitions between your cover view and your list view of album tracks, this code shows my transition and references views that are not part of this example/answer, but you don't need those - you'll have your own cover view (musicPlayerView) and list view (musicQueueView) to flip between.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:([musicQueueView superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.contentView cache:YES];
if ([musicQueueView superview]) { // if music queue is displayed
[musicQueueView removeFromSuperview];
[self.contentView addSubview:musicPlayerView];
} else {
[musicPlayerView removeFromSuperview];
[self.contentView addSubview:musicQueueView];
[[musicQueueView queueTableView] reloadData];
}
[UIView commitAnimations];*/
}

How to animate View swap on simple View iPhone App?

Have a simple iPhone app with a single UIViewController and two Views in one xib.
the first view is very simple with a button and upon button press the second more complex view is loaded via setting the view property on the controller.
what I would like is to animate the view swap (flip the views).
The samples I have seen all require having multiple view controllers and building a hierachy, but that would be overkill in this case, any suggestions?
Make sure you declare IBOutlets for the two views in your view controller I am assuming that in your xib you have a 'container view' that occupies the whole screen, and two views of the same size that you add to this contatiner (one for each side of your 'flip'):
//Inside your .h:
IBOutlet UIView *firstView;
IBOutlet UIView *secondView;
Make sure on initial load you have the firstView show up:
-(void) viewDidLoad {
NSAssert(firstView && seconView, #"Whoops: Are first View and Second View Wired in IB?");
[self.view addSubview: firstView]; //Lets make sure that the first view is shown
[secondView removeFromSuperview]; //Lets make sure that the second View is not shown at first
}
Then you can wire up a button like this, make sure the button is wired to this metod in IB:
-(IBAction) flipButtonPressed:(id) sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
if ([firstView superview]) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[firstView removeFromSuperview];
[self.view addSubview:secondView];
}
else if ([secondView superview]) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[secondView removeFromSuperview];
[self.view addSubview:firstView];
}
[UIView commitAnimations];
}