Reputation: 30015
I have a class of UINavigationController (and linked to the storyboard "mainNavCont") containing:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"init");
}
- (void)viewDidAppear:(BOOL)animated
{
NSLog(@"View Appeared");
UINavigationController *selfNavController = [self navigationController];
[selfNavController performSegueWithIdentifier:@"rootToPortSeg" sender:self];
}
There is a segue in the storyboard with the identifier "rootToPortSeg", type is "push", that links to a UIViewController called "portViewCont". In that class there is the following:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"I am the port");
}
Everything compiles fine and I get no errors in Xcode. But the portViewCont UIViewController never loads or displays or anything. I am still new to iOS and for the life of me I can't figure out what I am doing wrong. I get "init" and "View Appeared" in the console but not "I am the port", Thanks SO!
Upvotes: 1
Views: 4811
Reputation: 104092
After thinking some more about this problem, I think the best way to go would be to use a custom container controller with a portraitController and landscapeController as its children.
In the following code, I instantiate the 2 child controllers in the container controller's init method, and have strong properties pointing to them so, that when switching back and forth, you'll be accessing the same instances. I set up the initial view controller in the method that checks for the device orientation at start-up, and then do the switching of the controllers in a call back to the UIDeviceOrientationDidChangeNotification. Finally, the actual switching with animation is done using the transitionFromViewController:toViewController:duration:options:animations:completion: method.
#import "ContainerController.h"
#import "LandscapeController.h"
#import "PortraitController.h"
@implementation ContainerController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
self.portCont = [[PortraitController alloc]initWithNibName:@"PortraitController" bundle:nil];
self.landCont = [[LandscapeController alloc] initWithNibName:@"LandscapeController" bundle:nil];
[self performSelectorOnMainThread:@selector(checkLaunchOrientation) withObject:nil waitUntilDone:NO];
}
return self;
}
-(void)checkLaunchOrientation {
if ([[UIDevice currentDevice] orientation] !=0) {
if (UIDevice.currentDevice.orientation == UIDeviceOrientationPortrait | UIDevice.currentDevice.orientation == UIDeviceOrientationPortraitUpsideDown){
if ([self.currentController class] != [self.portCont class] ) {
self.currentController = self.portCont;
[self addChildViewController:self.portCont];
[self.view addSubview:self.portCont.view];
}
}else if (UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeLeft | UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeRight){
if ([self.currentController class] != [self.landCont class] ) {
self.currentController = self.landCont;
[self addChildViewController:self.landCont];
[self.view addSubview:self.landCont.view];
}
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}else{
[self checkLaunchOrientation];
}
}
-(void)orientationChanged:(NSNotification *) aNote {
if (UIDevice.currentDevice.orientation == UIDeviceOrientationPortrait | UIDevice.currentDevice.orientation == UIDeviceOrientationPortraitUpsideDown){
if ([self.currentController class] != [self.portCont class] ) {
[self addChildViewController:self.portCont];
[self moveToNewController:self.portCont];
}
}else if (UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeLeft | UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeRight){
if ([self.currentController class] != [self.landCont class] ) {
[self addChildViewController:self.landCont];
[self moveToNewController:self.landCont];
}
}
}
-(void)moveToNewController:(id) newController {
[self.currentController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{}
completion:^(BOOL finished) {
[self.currentController removeFromParentViewController];
[newController didMoveToParentViewController:self];
self.currentController = newController;
}];
}
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
Upvotes: 1
Reputation: 438212
I liked where rdelmar was going on his analysis, but as you saw, it looks like you can't perform a push segue from the navigation controller itself (which makes sense). But, it looks like you can instantiateViewControllerWithIdentifier
, then you can pushViewController
to that from the navigation controller fine. Thus, if the subclassed UINavigationController
has a viewDidLoad
like:
- (void)viewDidLoad
{
[super viewDidLoad];
// this is the storyboard identifier for the portrait view controller
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"portrait"];
// now you can push to it
[self pushViewController:controller animated:NO];
}
Then, the portrait view is loaded, you see its @"I am the port"
, you see the controls you added in Interface Builder for that view, etc.
Update:
I have to confess that while the above technique works, I wonder if that's the best way. Specifically, looking at your storyboard, I'm inferring that your goal is to have one view controller for portrait and another for landscape. If that's what you want to do, you can just use the technique that Apple lays out in their View Controller Programming Guide in the Creating an Alternate Landscape Interface section.
Maybe you can describe why you're using a navigation controller to do this, when it wasn't really designed to handle that. It's really more geared towards handling the pushing and popping of view controllers, not for choosing between different view controllers. I think you can make it work, but I wonder if the technique described in the View Controller Programming Guide might be more appropriate. But maybe you have some functional requirement that is not immediately apparent from your storyboard.
Upvotes: 1
Reputation: 104092
If I understand your setup correctly, the code you posted is in your MainNavCont controller. If that's so, I don't understand what you're doing with this line:
UINavigationController *selfNavController = [self navigationController];
The class your code is in is the navigation controller, you should just be using self in the performSegue: method:
[self performSegueWithIdentifier:@"rootToPortSeg" sender:self];
Upvotes: 0