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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top