title: Switch between two UIViewControllers programmatically
body: <p>I have two xib files and for each it's own class which overrides UIViewController class. I have a button in first xib file which should take me to new UIViewController when it's pressed. I have managed to make that transition in different ways:</p>
  
  <pre><code>UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:@"SecondViewControllerName" bundle:[NSBundle mainBundle]];
          [self.view addSubview:secondViewController.view];
  </code></pre>
  
  <p>or</p>
  
  <pre><code>UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:@"SecondViewControllerName" bundle:[NSBundle mainBundle]];
          [self.navigationController pushViewController:secondViewController animated:YES];
  </code></pre>
  
  <p>In second UIViewController xib file I have also one button which should take me back to first UIViewController. But I don't know how to navigate back to first UIViewController.</p>
  
  <p>I tried:</p>
  
  <pre><code>[self.navigationController popViewControllerAnimated:YES];
  </code></pre>
  
  <p>for second way of navigating to second UIViewController, but I get <em>unrecognized selector sent to instance</em> error.</p>
  
  <p>Many thanks in advance for any kind of help.</p>
  
  <hr>
  
  <p><strong>[edit #1: Adding source code]</strong></p>
  
  <p>Here's source code of first view controller .m file:</p>
  
  <pre><code>#import "ViewController.h"
  #import "SecondViewController.h"
  
  @interface ViewController ()
  
  @end
  
  @implementation ViewController
  
  - (void)viewDidLoad
  {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
  }
  
  - (void)viewDidUnload
  {
      [super viewDidUnload];
      // Release any retained subviews of the main view.
  }
  
  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
      return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
  }
  
  - (IBAction)switchToSecondPage:(id)sender
  {
      SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
  
      [UIView beginAnimations:@"flipping view" context:nil];
      [UIView setAnimationDuration:1];
      [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
      [UIView setAnimationTransition: UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
  
      [self.view addSubview:secondViewController.view];
  
      [UIView commitAnimations];  
  
  }
  
  @end
  </code></pre>
  
  <p>Here's source code of second view controller .m file:</p>
  
  <pre><code>#import "SecondViewController.h"
  
  @interface SecondViewController ()
  
  @end
  
  @implementation SecondViewController
  
  - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  {
      self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
      if (self) {
          // Custom initialization
      }
      return self;
  }
  
  - (void)viewDidLoad
  {
      [super viewDidLoad];
      // Do any additional setup after loading the view from its nib.
  }
  
  - (void)viewDidUnload
  {
      [super viewDidUnload];
      // Release any retained subviews of the main view.
      // e.g. self.myOutlet = nil;
  }
  
  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
      return (interfaceOrientation == UIInterfaceOrientationPortrait);
  }
  
  - (IBAction)switchToFirstPage:(id)sender
  {
      [UIView beginAnimations:@"flipping view" context:nil];
      [UIView setAnimationDuration:1];
      [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
      [UIView setAnimationTransition: UIViewAnimationTransitionCurlUp forView:self.view.superview cache:YES];
  
      [self.view removeFromSuperview];
  
      [UIView commitAnimations];
  }
  
  @end
  </code></pre>
  
  <p>Here's my AppDelegate.m file:</p>
  
  <pre><code>#import "AppDelegate.h"
  
  #import "ViewController.h"
  
  @implementation AppDelegate
  
  @synthesize window = _window;
  @synthesize viewController = _viewController;
  
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
      self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
      // Override point for customization after application launch.
      self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
      self.window.rootViewController = self.viewController;
      [self.window makeKeyAndVisible];
      return YES;
  }
  
  - (void)applicationWillResignActive:(UIApplication *)application
  {
  }
  
  - (void)applicationDidEnterBackground:(UIApplication *)application
  {
  }
  
  - (void)applicationWillEnterForeground:(UIApplication *)application
  {
  }
  
  - (void)applicationDidBecomeActive:(UIApplication *)application
  {
  }
  
  - (void)applicationWillTerminate:(UIApplication *)application
  {
  }
  
  @end
  </code></pre>
  
  <p>Entire project is made as Single View Application and targeted for iOS 5.1 in XCode 4.3. I have found sample project which does the same thing I am having trouble with. Here's URL for that project: <a href="http://www.devx.com/wireless/Article/42476/0/page/2" rel="nofollow">http://www.devx.com/wireless/Article/42476/0/page/2</a>
  It is just written for earlier iOS version. Is anyone able to see what am I doing wrong, since I am really out of ideas?</p>
  
  <p>PS: With this animations in code, or without - same problem occurs, so animations aren't problem, I've checked that.</p>
  
  <hr>
  
  <p><strong>[edit #2: Adding error info]</strong></p>
  
  <p>Here's error description. In main method on return line as listed below:</p>
  
  <pre><code>int main(int argc, char *argv[])
  {
      @autoreleasepool {
          return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
      }
  }
  </code></pre>
  
  <p>I get this error:</p>
  
  <blockquote>
    <p>Thread 1: EXC_BAD_ACCESS (code=1, address=0xc00000008)</p>
  </blockquote>
  
  <hr>
  
  <p><strong>[edit #3: SOLUTION]</strong></p>
  
  <p>I would like to thank @btype for his solution below. I found out why code from edit #2 didn't work. Problem was doing this:</p>
  
  <pre><code>SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
  </code></pre>
  
  <p><strong>INSIDE OF IBAction METHOD!</strong> Looks like ARC wiped my UIViewController as soon as end of scope was reached and that's why I was getting informations about sending messages to released instance. I made SecondViewController private field in my ViewController class and after that everything worked just fine.</p>
  
  <p>If anyone thinks my explanation is wrong and knows what really bothered me, feel free to answer to this question and correct me.</p>