Background & Objective: I have a UISplitViewController based iPad app - till now it supported 4 orientations but now I want to lock it down to only landscape.
I changed shouldAutorotateToInterfaceOrientation
of the left view controller to support only landscape mode, but this stops its viewWillAppear
from getting called.
Details: My iPad's view controllers are organized as below:
window
`-- splitVC (UISplitViewController)
`-- rootNav (UINavigationController)
`-- hvc (HostManagerViewController, derived from UIViewController)
`-- detailViewController (DetailViewController, derived from UIViewController)
This is implemented in the App Delegate as below:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HostManagerViewController *hvc = [[[HostManagerViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
self.detailViewController = [[[DetailViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
UINavigationController *rootNav = [[[UINavigationController alloc]
initWithRootViewController:hvc] autorelease];
UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease];
[splitVC setViewControllers:[NSArray arrayWithObjects:rootNav,
detailViewController, nil]];
splitVC.delegate = detailViewController;
[window addSubview:splitVC.view];
[window setRootViewController:splitVC];
return YES;
}
viewWillAppear
gets called when both DetailViewController.m
and HostManagerViewController.m
contain
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Console output:
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Hostmanager: viewwillappear
But when I change HostManagerViewController
's code to
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
then 'viewWillAppear` of HostManagerViewController is not invoked. Console output
Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation)
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Only Landscape modes are supported in the Info.plist
EDIT: Inserted NSLog messages to track shouldAutorotateToInterfaceOrientation
, viewWillAppear
and ViewDidLoad
I asked what iOS version you were using because I tried to create a simple reproduction of your problem and found the behavior differs between 4.3 and 5.0. It actually does make all the correct calls in 5.0. I believe this to simply be a bug with the UISplitviewController. Splitview controller was quite buggy. aopsfan's answer does not solve the problem (I have confirmed this). I would suggest subclassing uisplitviewcontroller, and overriding the splitview controller's viewwillappear, viewdidappear like so:
#import "testSplitViewController.h"
@implementation testSplitViewController
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString *reqSysVer = @"5.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
[[[self viewControllers] objectAtIndex:0] viewWillAppear:animated];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSString *reqSysVer = @"5.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
[[[self viewControllers] objectAtIndex:0] viewDidAppear:animated];
}
@end
You have to check the version number so that you don't make the viewDidAppear call twice.
Or just go with 5.0 or above if you can, since the bug seems to be fixed.
Basically, since a UISplitViewController
has two parts, you need a universal implementation of shouldAutorotate. I suppose that tackling the rotation of the view controllers individually can cause some weird side affects--though please take note that I was not able to replicate your viewWillAppear
issue, so this solution is really a guess.
I would recommend making a dead-simple subclass of UISplitViewController
. Name it "SplitViewController", and in it's .m
file, delete everything except shouldAutorotate, which will look like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
Now change your shouldAutorotate code in HostManagerViewController
and DetailViewController
back to:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Now, in your app delegate, use this class instead of UISplitViewController
. This should (may) fix your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With