I have a single view app with 2 view controllers to present different layouts for portrait and landscape. I have set up the orientation changed notifications and can successfully display the landscape view on the first orientation change.
1st Problem: When I change the orientation back to portrait the portrait view is not displayed.
2nd Problem: When I change the orientation back to landscape the landscape view displays but I get a warning:
Attempt to present CalculatorViewControllerLandscape on CalculatorViewController whose view is not in the window hierarchy.
I have been through the apple documentation and several posts with similar problems and have figured out that the answer lies in the use of delegation but I have not been able to get delegation set up correctly. Here is my attempt:
CalculatorViewControllerLandscape.h
@protocol SecondControllerDelegate <NSObject>
@end
.....
@property(nonatomic, weak) id <SecondControllerDelegate> delegate;
CalculatorViewController.h
@interface CalculatorViewController : UIViewController <SecondControllerDelegate> {
....
}
@property (strong) CalculatorViewControllerLandscape *landscapeVC;
CalculatorViewCalculator.m
- (void)awakeFromNib
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
// register as a delegate
self.navigationController.delegate = (id)self;
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
NSLog(@"Orientation has changed to landscape");
// code here to show landscape storyboard
UIStoryboard *landscapeStoryboard = [UIStoryboard storyboardWithName:@"LandscapeStoryboard" bundle:nil];
UIViewController *landscapeViewController = [landscapeStoryboard instantiateInitialViewController];
[self presentViewController:landscapeViewController animated:YES completion:nil];
isShowingLandscapeView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
isShowingLandscapeView)
{
NSLog(@"Orientation has changed to portrait");
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
isShowingLandscapeView = NO;
}
}
I've been working on this for several hours and have checked all posts which similar problems but I still can't figure it out. Thanks in advance for help.
Best practice is to handle rotation events in a single UIViewController
, rather than using two separate ones. I'm not familiar with interface builder, but programmatically you can override -(void)viewWillLayoutSubviews;
and lay out your view appropriately based on self.interfaceOrientation
. I recommend you do it that way.
However, in answer to your question:
try changing
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
to
[self dismissViewControllerAnimated:NO completion:nil];
This may fix the 2nd problem as well, because the old landscape view controller not being properly dismissed.