views:

567

answers:

4

Hi,

I've found many tutorials on switching views on the iPhone but none that quite match my needs. I wonder if you can help.

I'm looking to have an initial view, A and on a button press unload A and switch to view B.

I've seen the following, but I have reasons why I don't want to do it that way:

Using a navigation controller - Once view A is discarded, I don't need to return to it, so it should disappear completely and be deallocated from memory.

Using a Tab bar controller - same reason as above. I'd like to linearly move from A to B and not B to A - ever.

Using a modal view - actually, the same reason. Also this feels like a bit of a UI no-no, since it gives the user the impression that they're coming back to view A once an action in B is complete.

Please help me, the one thing I'm really struggling with is how to unload the original view controller that's created as part of the app. I think to show the other view all I need to do is init and alloc it in View A, then add it as a subview. However, unloading view A from viewcontroller A is really baffling me.

Thanks in advance!

Edit: On advice from someone below I've implemented view switching, but for some reason removeFromSuperview doesn't work on View A after View B is displayed. Basically I can still see view A behind view B (I made view b slightly smaller so I could test this).

Here's my app delegate:

@implementation View_SwitchAppDelegate

@synthesize window;
@synthesize switchViewController;
@synthesize secondViewController;
@synthesize firstViewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
    FirstViewController *aFirstView = [[FirstViewController alloc] initWithNibName:@"FirstView" bundle:nil];
    [self setFirstViewController:aFirstView];
    [aFirstView release];
    [window addSubview:firstViewController.view];
    [window makeKeyAndVisible];
}


- (void)dealloc {
    [window release];
    [switchViewController release];
    [super dealloc];
}

- (void)switchToTwo {
    SecondViewController *aSecondView = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil];
    [self setSecondViewController:aSecondView];
    [aSecondView release];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:window cache:YES];
    [firstViewController.view removeFromSuperview];

    [firstViewController release];
    firstViewController = nil;

    [self.window addSubview:[secondViewController view]];

    [window makeKeyAndVisible];
    [UIView commitAnimations];
}

@end

Here's my FirstViewController (You'll see that when the camera picker returns an image, I try to switch views by calling the app delegate method:

#import "FirstViewController.h"
#import "View_SwitchAppDelegate.h"
#import "SecondViewController.h"

@implementation FirstViewController

- (IBAction) takeButtonPressed 
{ 
   NSString *type = @"Camera";
    [self callCameraWithType:type];
} 
- (IBAction) chooseButtonPressed 
{ 
    NSString *type = @"Library"; 
    [self callCameraWithType:type];
} 

-(void) callCameraWithType:(NSString *)type {

    // Set up the image picker controller and add it to the view
    imagePickerController = [[UIImagePickerController alloc] init];
    imagePickerController.delegate = self;

    if ([type isEqual:@"Camera"])
    {
     NSLog(@"Camera");
     if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
      imagePickerController.sourceType = 
      UIImagePickerControllerSourceTypeCamera;
     }
     else {
      imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
     }
    }
    else
    {
     NSLog(@"Library");
     imagePickerController.sourceType = 
     UIImagePickerControllerSourceTypePhotoLibrary;
    }

    [self presentModalViewController:imagePickerController animated:YES];
}

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [picker dismissModalViewControllerAnimated:YES];

    //get app delegate
    View_SwitchAppDelegate *appDelegate = (View_SwitchAppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate switchToTwo];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{

    // Dismiss the image selection and close the program
    [picker dismissModalViewControllerAnimated:YES];

}
/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    NSLog(@"View loaded");
    [super viewDidLoad];
}


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}
- (void)removeSelf{
    [self.view removeFromSuperview];
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    NSLog(@"First Unload");
}


- (void)dealloc {
    NSLog(@"First Dealloc");
    [super dealloc];
}


@end
A: 

Well, if you use presentmodalviewcontroller and set animated to NO, they won't be put under the impression that they are going back. Otherwise, there is no other way that I know of.

Flafla2
+1  A: 

you can try stmh like this

[myNavigationController setViewControllers:[NSArray arrayWithObject:viewControllerB] animated:NO];
Morion
A: 

Your application's main view should contain a subview which is initially view A. The main view doesn't have to have anything else in it.

To switch views, just remove A and replace it with the new view. You can even animate the new view so it slides in from wherever, or zooms in, or fades in, or whatever.

This is pretty trivial and I do it all the time. My main view has a title bar (which is just a UILabel) and a tool bar (UIToolbar). Between the two is my "document" which can be switched out for another.

Craig
Thanks. I tried something similar to this. In View A's ViewController I had [self.view removeFromSuperview]; but that didn't seem to actually remove the view?
mac_55
+1  A: 

Why not roll your own view controller, that when you call removes a view and replaces with another?, something like this

if (firstViewController.view.superview !=nil)

{ if(self.secondViewController == nil) { secondViewController *secondViewController = [[secondViewController alloc] initWithNibName:@"secondSavesView" bundle:nil]; self.secondViewController = secondViewController; [secondViewController release]; }

            [firstViewController.view removeFromSuperview];

//probably include some animation here [detailView insertSubview:secondViewController.view atIndex:0]; }

kgutteridge
I have tried this, but removeFromSuperview doesn't seem to work, the new view is added but the old one still remains
mac_55
Can you provide some example code showing what you did? removeFromSuperview most definitely works if you've done things correctly, but there's no way for us to know if you don't post code.
John Biesnecker
Thanks, I've added some code in my original question.
mac_55