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:
UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:@"SecondViewControllerName" bundle:[NSBundle mainBundle]];
[self.view addSubview:secondViewController.view];
or
UIViewController* secondViewController = [[UIViewController alloc] initWithNibName:@"SecondViewControllerName" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:secondViewController animated:YES];
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.
I tried:
[self.navigationController popViewControllerAnimated:YES];
for second way of navigating to second UIViewController, but I get unrecognized selector sent to instance error.
Many thanks in advance for any kind of help.
[edit #1: Adding source code]
Here’s source code of first view controller .m file:
#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
Here’s source code of second view controller .m file:
#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
Here’s my AppDelegate.m file:
#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
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: http://www.devx.com/wireless/Article/42476/0/page/2
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?
PS: With this animations in code, or without – same problem occurs, so animations aren’t problem, I’ve checked that.
[edit #2: Adding error info]
Here’s error description. In main method on return line as listed below:
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
I get this error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0xc00000008)
[edit #3: SOLUTION]
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:
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
INSIDE OF IBAction METHOD! 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.
If anyone thinks my explanation is wrong and knows what really bothered me, feel free to answer to this question and correct me.
Edit the code:
in AppDelegate.m
FirstViewController.m
SeconViewController.m
This should help.