Present UIViewController from Side - iphone

I'm trying to present a UIViewController from the side.
The only thing that Present Modal can do is Verticle Slide in.
Any body have any ideas about this?
Let me know' thanks

To be anal about the MVC, its really the View your moving and not the controller.
I would recommended the way of doing this would be to use a navigation controller, it's animation is a horizontal slide by default and you get a navigation stack for free- this means that you have back buttons auto generated and, title and button properties that you can set, although these can be hidden easily is desired.
Using a navigation controller:
create a UINavigationsController property in your parent controller, syth, alloc and init it appropriately. Then you can load the controllers in in any order you want and it looks after the navigation.
Here is a good tutorial on NavControllers (usually they are used with UITableViewControllers but don't have to be)
Peng's example is an animation and I should note that it removes the parent view (and depending on your design might not just remove the 'currentView' - as your/a top view might be a subView) so if your navigating back you would have to handle this yourself.

I did this and it worked, though I don't know if there is a more official way to do it (UIVIewAimationTransition doesn't have a slide option):
UIView *currentView = self.view;
UIView *theWindow = [currentView superview];
[currentView removeFromSuperview];
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#"SwitchToView1"];

I just gave this answer to another SO question that was very similar, but here it is again, in case folks looking end-up here, instead.
All of the ViewControllers in my app inherit from MyViewController which, in addition to some other default behaviours, has this property:
#property(readwrite, nonatomic) BOOL slideFromSide;
And this code:
- (void) presentViewController: (UIViewController*) vc animated: (BOOL) flag completion: (void (^)(void)) completion
{
BOOL slideIn = NO;
if ([vc isKindOfClass: [MyViewController class]])
{
MyViewController *svc = (MyViewController*) vc;
slideIn = svc.slideFromSide;
}
if (slideIn)
{
[self addChildViewController: vc];
[self.view addSubview: vc.view];
CGRect frame = vc.view.frame;
frame.origin.x = frame.size.width;
vc.view.frame = frame;
frame.origin.x = 0;
[UIView animateWithDuration: 0.33
animations: ^{
vc.view.frame = frame;
}
];
}
else
{
[super presentViewController: vc animated: flag completion: completion];
}
}
- (IBAction) backAction: (id) sender
{
if (_slideFromSide)
{
CGRect frame = self.view.frame;
frame.origin.x = frame.size.width;
[UIView animateWithDuration: 0.33
animations: ^{
self.view.frame = frame;
}
completion:^(BOOL finished) {
[self removeFromParentViewController];
}
];
}
else
{
[self dismissViewControllerAnimated: YES completion: nil];
}
}
Then, in the ViewControllers where I want to slide-in, I have:
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil];
if (self)
{
self.slideFromSide = YES;
// Whatever else you want to do
}
return self;
}
Calling a new ViewController is just like normal:
WhateverViewController *vc = [WhateverViewController alloc] initWithNibName: nil bundle: nil];
[self presentViewController: vc animated: YES completion: nil];

Related

How to make custom segue with left push effect?

My application is displaying Arabic text in which i want push animation from left side and not from right side which ios provides by default.
I am using storyboards.I have created custom segue.
I have gone through all options cocoacontrols but have not found desired one.
I have found several options as follows:
1) CATransition
2) Animation
3) maintaining view controllers array - which creates lot of mess
Below code gives perfect effect but black patches as show below are not acceptable -
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
transition.duration = .25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromLeft; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[sourceViewController.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[sourceViewController.navigationController pushViewController:destinationController animated:NO];
[destinationController.view setBackgroundColor:[UIColor whiteColor]];
}
Implemented below code give no black patches - but not desired animation
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationViewController = (UIViewController*)[self destinationViewController];
[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
[destinationViewController.view setAlpha:1.0];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
[destinationViewController.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
[destinationViewController.view setAlpha:1.0];
}
completion:^(BOOL finished){
[destinationViewController.view removeFromSuperview];
[sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
}];
}
By changing above code - but i am not getting desired result
-(void)perform{
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationViewController = (UIViewController*)[self destinationViewController];
[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setAlpha:1.0];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
sourceViewController.view.frame = CGRectMake(sourceViewController.view.frame.size.width*2, 0, sourceViewController.view.frame.size.width, sourceViewController.view.frame.size.height);
}
completion:^(BOOL finished){
[sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
}];
}
use below code In appDelegate.m - applicationDidFinishLaunchingWithOptions
self.window.backgroundColor = [UIColor whitecolor];
This is a custom segue in swift that uses the messy way, manipulates list of view controllers.. Anyway, I wanted to push to a view controller, but make it look like it was a pop, and I tried to do it with all sorts of animations, but in the end - for me, this was the most simplest way to get what I wanted as I don't have to maintain my code, if iOS styling changes and so on, as it uses general pop - it should remain the same as default pop in the system.. Anyway, to the code:
class ReversePushSegue : UIStoryboardSegue {
override func perform() {
let sourceViewController = self.sourceViewController as UIViewController
let destinationViewController = self.destinationViewController as UIViewController
var vcs : NSMutableArray = NSMutableArray(array: sourceViewController.navigationController.viewControllers)
vcs.insertObject(destinationViewController, atIndex: vcs.count - 1)
sourceViewController.navigationController.viewControllers = vcs
sourceViewController.navigationController.popViewControllerAnimated(true)
}
}
What it does - it adds destinationViewController to the list as second last and then pops to it..

Add child view controller to UINavigationController

I'm trying to add a child view controller to a UIViewController contained in a UINavigationController with this code:
- (void)buttonTapped:(id)sender
{
MyChildController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"MyChild"];
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];
viewController.view.alpha = 0.0f;
[UIView animateWithDuration:0.4 animations:^{
viewController.view.alpha = 1.0f;
}];
}
But this is the result:
As you can see the UINavigatioBar and the UIToolbar are still on top of the child view controller. How can I put the child view controller on top of all? I've already tried to replace the code with:
[self.navigationController addChildViewController:viewController];
[self.navigationController.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self.navigationController];
But in this way the viewDidAppear:animated of the viewController doesn't get called. I don't know, why.
#Sam's comment is correct. You need to call beginApperanceTransition:animated: and endAppearanceTransition for viewDidAppear to be triggered. The reason why UINavigationController does not call viewDidAppear when you add a child view controller is because it has overridden its container composition methods to prevent the programmer from adding a child view controller in strange places. In your case, it doesn't want your child view to cover up the navigation bar. The correct usage of a navigation controller is to have children appear under the navigation bar. Nonetheless, you can still force upon this non-standard UI by manually telling the child when it is appearing and when it has finished appearing.
Add a child to UINavigationController
MyChildViewController* child = [[MyChildViewController alloc] init];
[self.navigationController addChildViewController:child];
child.view.frame = self.navigationController.view.bounds;
[self.navigationController.view addSubview:child.view];
child.view.alpha = 0.0;
[child beginAppearanceTransition:YES animated:YES];
[UIView
animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^(void){
child.view.alpha = 1.0;
}
completion:^(BOOL finished) {
[child endAppearanceTransition];
[child didMoveToParentViewController:self.navigationController];
}
];
Remove a child from UINavigationController
[child willMoveToParentViewController:nil];
[child beginAppearanceTransition:NO animated:YES];
[UIView
animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^(void){
child.view.alpha = 0.0;
}
completion:^(BOOL finished) {
[child endAppearanceTransition];
[child.view removeFromSuperview];
[child removeFromParentViewController];
}
];
In your first view controller, do something like this:
- (IBAction)buttonClick:(id)sender
{
SecondViewController *secondView = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
UIImage *blurryImage = [UIImage imageNamed:#"foo.jpeg"];
secondView.imageView.image = blurryImage;
[self.navigationController addChildViewController:secondView];
secondView.view.frame = self.navigationController.view.frame;
[self.navigationController.view addSubview:secondView.view];
}
Then in your second view controller, add the getter for your imageview:
-(UIImageView *)imageView
{
if( _imageView == nil )
{
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 548)];
[self.view addSubview:_imageView];
}
return _imageView;
}
#Pwner's answer Swift version:
Add child to UINavigaitonController
let child = MyChildViewController()
self.navigationController?.addChildViewController(child)
guard let navigationController = navigationController else {
return
}
child.view.frame = navigationController.view.bounds
child.beginAppearanceTransition(true, animated: true)
self.navigationController?.view.addSubview(child.view)
self.view.alpha = 0
UIView.animate(withDuration: 0.3, animations: {
child.view.alpha = 1.0
}, completion: { _ in
guard let navigationController = self.navigationController else {
return
}
child.endAppearanceTransition()
child.didMove(toParentViewController: navigationController)
})
Remove a child from UINavigationController
child.willMove(toParentViewController: nil)
child.beginAppearanceTransition(false, animated: true)
UIView.animate(withDuration: 0.3, animations: {
child.view.alpha = 0.0
}, completion: { _ in
guard let navigationController = self.navigationController else {
return
}
child.view.removeFromSuperview()
child.endAppearanceTransition()
child.removeFromParentViewController()
})

Changing Push ViewController animation to look like a "pop" animation, come in from left to right

Right now I am using a segue from storyboard to push a view controller and there is just the one push transition. How can I imitate the "Pop" transition in code? Can I do this while still using storyboard for my other transitions in place now?
UPDATE
I tried what is suggested in the first comment here, with some changes. Here's what I have:
UIViewController *dst = [self destinationViewController];
UIViewController *src = [self sourceViewController];
[dst viewWillAppear:YES];
[dst viewDidAppear:NO];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGRect f = CGRectMake(-screenBounds.size.width, 0, screenBounds.size.width, screenBounds.size.height);
dst.view.frame = f;
f.origin.x = screenBounds.size.width;
src.view.frame = f;
[UIView transitionFromView:src.view
toView:dst.view
duration:0.3
options:UIViewAnimationOptionTransitionNone
completion:^(BOOL finished){
[dst viewDidAppear:YES];
UINavigationController *nav = src.navigationController;
[nav popViewControllerAnimated:NO];
[nav pushViewController:dst animated:NO];
}];
This is working almost how I want, but the original viewcontroller is just disappearing instead of sliding to the right.
You can create Segue type "Custom" on your stroyboard and create a new UIStoryboardSegue class named "popSegue" In the popSegue.m file add this:
-(void)perform{
UIViewController *sourceViewContreoller = [self sourceViewController];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionFromLeft]; //or kCATransitionFromRight
[animation setDuration:0.25];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseIn]];
[sourceViewContreoller.navigationController.view.layer addAnimation:animation forKey:#"animateOpacity"]; //or key=#"fadeTransition"
[sourceViewContreoller.navigationController popViewControllerAnimated:YES];
[CATransaction commit];
}
In the storyboard editor Select the segue and change the Segue Class to "popSegue".
Set the Identifier to "popSegue".
Try this and comment for your result

Unclear on how to properly remove a UIViewController from another UIViewController

thank you for your time, (As a side note, this question pertains mostly to iOS 4.2.3, I am aware some of these issues could be resolved with moving the code base to iOS 5, however we would like to release this app for phones running iOS 4 as well.)
I have a "MasterViewController" that is in charge of calling and dismising other UIVIewControllers.
First we trigger a new one:
In MasterViewController.m
-(IBAction)triggerPrime:(id)sender {
[self clearHomeScreen];
NSUInteger randomNumber = arc4random() % 2;
if (randomNumber == 0) {
self.flashTextViewIsDisplayed = NO;
ThinkOfViewController *thinkVC = [[ThinkOfViewController alloc] initWithNibName:#"ThinkOfViewController" bundle:nil];
self.thinkOfViewController = thinkVC;
[thinkVC release];
self.picturePrimeViewIsDisplayed = YES;
[self.view addSubview:self.thinkOfViewController.view];
}
else if (randomNumber == 1) {
self.picturePrimeViewIsDisplayed = NO;
FlashTextPrimeViewController *flashVC = [[FlashTextPrimeViewController alloc] initWithNibName:#"FlashTextPrimeViewController" bundle:nil];
self.flashTextPrimeViewController = flashVC;
[flashVC release];
self.flashTextViewIsDisplayed = YES;
[self.view addSubview:self.flashTextPrimeViewController.view];
}
Let's say that our randomNumber is 0, and it adds the ThinkOfViewController to the subview, (This is a very basic screen, it essentially displays some text with some assets animating:
In ThinkOfViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.thinkOf.alpha = 0.0;
self.dot1.alpha = 0.0;
self.dot2.alpha = 0.0;
self.dot3.alpha = 0.0;
self.background.alpha = 0.0;
[self animateViews];
}
-(void)animateViews {
[UIView animateWithDuration:0.25 animations:^ {
self.background.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.75 delay:0.00 options:UIViewAnimationCurveEaseIn animations:^ {
self.thinkOf.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot1.alpha = 1.0;
}completion:^(BOOL finsihed) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot2.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot3.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.50 delay:0.60 options:UIViewAnimationCurveEaseInOut animations:^{
self.view.alpha = 0.0;
}completion:^(BOOL finished) {
NSLog(#"all animations done");
[[NSNotificationCenter defaultCenter] postNotificationName:#"removeThinkOfView" object:nil];
}];
}];
}];
}];
}];
}];
}
As you can see, once the animation sequence is finished, I post a notification to NSNotificationCenter (which resides in the MasterViewController) to remove this viewController.
In MasterViewController.m
-(void)removeThinkOfView {
[self.thinkOfViewController.view removeFromSuperview];
[self showPicturePrime];
}
-(void)showPicturePrime {
if (self.picturePrimeViewController == nil) {
PicturePrimeViewController *pVC = [[PicturePrimeViewController alloc] initWithNibName:#"PicturePrimeViewController" bundle:nil];
self.picturePrimeViewController = pVC;
[pVC release];
[self.view addSubview:self.picturePrimeViewController.view];
}
else {
PicturePrimeViewController *pVC = [[PicturePrimeViewController alloc] initWithNibName:#"PicturePrimeViewController" bundle:nil];
self.picturePrimeViewController = pVC;
[pVC release];
[self.view addSubview:self.picturePrimeViewController.view];
}
}
Now a picturePrimeViewController is loaded and added to the subview, everything loads and displays fine. Now, to get a new prime, you simple swipe for a new one.
In picturePrimeViewController.m
-(void)handleSwipeFromRight:(UISwipeGestureRecognizer *)gestureRecognizer {
if (!transitioning) {
[self performTransition];
}
}
-(void)performTransition {
CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
transitioning = YES;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
[UIView animateWithDuration:0.5 animations:^ {
self.view.alpha = 0.0;
}completion:^(BOOL finished) {
NSLog(#"Transition Animation Complete");
}];
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
transitioning = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:#"nextPrime" object:nil];
}
Now in the animationDidStop: Method, i again post another notification to the NSNotificationCenter back to the MasterViewController to signal another prime.
In MasterViewController.m
-(void)nextPrime {
if (self.picturePrimeViewIsDisplayed) {
[self.picturePrimeViewController.view removeFromSuperview];
self.picturePrimeViewController = nil;
[self showAPrime];
}
if (self.flashTextViewIsDisplayed) {
[self.flashTextPrimeViewController.view removeFromSuperview];
self.flashTextPrimeViewController = nil;
[self showAPrime];
}
}
However! Upon swiping the right, the view animates properly but then I get a bad access crash when the ThinkOfViewController is attempting to dealloc it's UIViews. So for some reason, it is taking that the ThinkOfViewController a long time to dealloc, when I assumed when I called [self.thinkOfViewController removeFromSuperview], it should of been removed immeditately.
(Side note, the textFlashViewController has no problems, the only problems are comming with this ThinkOfViewController).
Is this paradigm I set up a bad implmentation of dealing with UiViewController's comming in and out? I have read that delegation can help in this instance, I'm just not sure how that works.
If any of you have any ideas, I would be so grateful, as I have mined through forums and documentations and cannot see a solution to my rather custom implmentation of dealing with these views.
So, the short answer is yes, this "paradigm" is a bad implementation of dealing with UIViewControllers. I would suggest going and reading Apple's View Controller Programming Guide, which outlines the correct implementation, but here's a quick synopsis:
Your MasterViewController, from what I gather, manages these other two UIViewControllers, ThinkOfViewController and PicturePrimeViewController. When you are adding or removing the views of a view controller from the screen, you don't add or remove the views to the MasterViewController. The whole point of a view controller is to manage the "showing" or "hiding" of its view. I put showing and hiding in quotes because you're not actually showing or hiding them. You are pushing and popping them off of the view hierarchy, and this is done with a UINavigationController. Each UIViewController knows the UINavigationController that it is being controlled by (thus, UINavigationControllers are known as "controllers of controllers"), and you can thus push a view controller onto the stack by saying
[self.navigationController pushViewController:vcToBePushed animated:YES];
When the view controller that is on top of the stack is to be removed, you simply have to say
[self.navigationController popViewControllerAnimated:YES];
Pushing or popping a UIViewController onto or off of the stack means the view controller takes its view with it, and displays it or removes it from on screen. So that covers, in the tightest nutshell imaginable, UIViewController view management.
The other issue, regarding the EXC_BAD_ACESS crash, means that you are trying to access memory that has already been allocated for another object. I suspect the culprit is here:
if (randomNumber == 0) {
self.flashTextViewIsDisplayed = NO;
ThinkOfViewController *thinkVC = [[ThinkOfViewController alloc] initWithNibName:#"ThinkOfViewController" bundle:nil];
self.thinkOfViewController = thinkVC;
[thinkVC release];
self.picturePrimeViewIsDisplayed = YES;
[self.view addSubview:self.thinkOfViewController.view];
}
The problem is that you release thinkVC before it has had a chance to be retained by the MasterViewController's view (which happens in self.view addSubview:). Thus, self.view is adding a pointer to an object whose memory just got added back to the heap. Scrapping your add/removeSubview methodology for the push/pop methodology I just outlined will keep that sort of memory issue from happening.
I hope this helps, but let us (us being SO) know if you still have issues.

Loading a nib file after finish using UIImagePickerController

I would like to know how can I load a new nib file after finishing with UIImagePicker Controller. So after the user takes a picture from the camera or albums, i would like to load a new nib for the user to do some editing. Below is the didFinishPickingMediaWithInfo. I can load an image to the current UIImageView or even send out and alertview, but even if I tried loading a new nib, it just goes back to currentview nib and no errors. Bear in mind that I'm a total ios noob, so if the method use is wrong, please let me know. Thanks in advance.
p.s. Just to add, even if I manage to load new nib, how do I pass the information from the previous nib? E.g. if I choose an image from nib2, how to pass it to nib3?
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
imageOverlay.image = [UIImage imageNamed:#"mask_overlay1.png"];
[imageOverlay release];
// Displaying image to the imageView
imageView.image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Tried to load a new nib
UIView *currentView = self.view;
// Get the underlying UIWindow, or the view containing the current view.
UIView *theWindow = [currentView superview];
//remove the current view and replace with myView1
[currentView removeFromSuperview];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#"createPhotoView"];
}
I have no idea what your app's workflow is like, but if you need to display a new view after an image is chosen, you should probably do it by either pushing a new view controller on to a navigation controller, or by presenting it as a modal view.
This allows you to easily return to the previous screen where you were asked to pick a photo.
Let's say that for your app, you decide to use a UINavigationController.
You would initialize a navigation controller with your first view controller as the root view controller.
Then, in your UIImagePicker delegate method, you would have something like this:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Initialize your new view controller
CustomViewController *controller = [[CustomViewController alloc] initWithNibName:#"SecondView" bundle:nil];
// Pass your custom view controller the image you just selected
controller.valueToPass = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
You create a subclass of UIViewController called CustomViewController, and pass it values by creating properties you can assign to (like valueToPass in my example).
EDIT:
It is possible to just switch the visible view of a view controller. It is as simple as changing the value of self.view. You could put two UIViews in the same XIB file, and put IBOutlets for both in your controller. You could have a header that looks like this:
#interface MyController : UIViewController {
IBOutlet UIView *view1;
IBOutlet UIView *view2;
}
// Follow this with properties for all of those IBOutlets as well
Then, in your controller code:
- (IBAction)switchViews {
if ([self.view isEqualTo:view1]) {
self.view = view2;
} else {
self.view = view1;
}
}
This works, but as far as I am aware, does not allow transitions. You could instead do this:
- (IBAction)switchViews:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];
if ([[secondaryView superview] isEqual:mainView]) {
[secondaryView removeFromSuperview];
} else {
[self.view addSubview:secondaryView];
}
[UIView commitAnimations];
}
Both of these options work, and allow you to use the same view controller to control both views. However, if the views perform different tasks, they should be associated with different controllers. Using different controllers is similar if you set up a controller as a property in your header:
- (IBAction)switchViews:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];
if (self.secondaryController) {
[self.secondaryController.view removeFromSuperview];
self.secondaryController = nil;
} else {
self.secondaryController = [[SecondaryController alloc] initWithNibName:#"SecondView" bundle:nil];
self.secondaryController.valueToPass = #"I am passing this value!";
[self.view addSubview:self.secondaryController.view];
}
[UIView commitAnimations];
}