I have my entire interface in one Storyboard. How can I make most of the ViewControllers only support a portrait orientation while only a couple supporting all orientations. I can't understand apples new auto rotate system. Also, how can I make this backwards compatable to iOS 5?
问题:
回答1:
In your Navigation Controller subclass, forward the decision to the top view controller in the stack:
-(NSUInteger) supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
Creating a separate storyboard file for this is the worst path to follow, it'll be a maintenance nightmare to keep them in sync with your app updates.
回答2:
You should watch the WWDC'2012 videos especially the ones in the "Essentials" section talking about rotations.
The one called "T Evolution of View Controllers in iOS" explains the subject about rotations (and how to make them compatible with various iOS version) in great details, with explanations and code samples, and I couldn't explain it better than Apple ;)
回答3:
Well i kinda hacked my way around this one. here is my Subclassed NavController.h
#import "RootVC.h"
@implementation RootVC
-(BOOL)shouldAutorotate {
def = [NSUserDefaults standardUserDefaults];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
if ([def integerForKey:@"Should Rotate"] == 1) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationMaskPortrait;
}
@end
I just set an integer for @"Should Rotate" in defaults on each View Controller in
- (void)viewWillAppear:(BOOL)animated
works like a charm!
回答4:
If you are using a native rootViewController, you have to extend it to support iOS5 gracefully. This is said in the above mentioned WWDC video.
Basically, if you are using a UINavigationViewController, extend it and override its - (NSUInteger)supportedInterfaceOrientations
method. In there, look into your children (you can just query the older methods for interface orientation you have) and determine what should be supported and return the correct value.
The reason you need to do this to be backward compatible is 2 things: - they've deprecated the old way of rotating stuff - only rootViewController ever gets the rotation call. The parent should decide for its children what orientation it needs to be in. All these changes are inline with the new AutoLayout stuff.
After you extend your nav controller, go to your storyboard -> select the root controller (navigation controller in this case) -> set the class to your newly written class.
HTH
回答5:
Here's a hack I used to support both iOS 5 devices and iOS 6 devices (as well as iPhone 5). In your prefix file, add the following #define
#ifdef __IPHONE_6_0 // Only do the rotation fix if we are building with iOS 6 API
@protocol DeprecatedRotationSupported
@optional
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation;
- (BOOL)shouldAutorotate;
- (NSUInteger)supportedInterfaceOrientations;
@end
#define shouldAutorotateToInterface_fixed shouldAutorotate \
{ \
UIViewController <DeprecatedRotationSupported> *selfTyped = (UIViewController <DeprecatedRotationSupported> *) self; \
\
if(![self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) \
return NO; \
int optionCount = 0; \
for(UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait; orientation <= UIDeviceOrientationLandscapeLeft; orientation++) \
{ \
if(![selfTyped shouldAutorotateToInterfaceOrientation:orientation]) continue; \
if(optionCount==1) return YES; \
optionCount++; \
} \
return NO; \
} \
\
- (NSUInteger)supportedInterfaceOrientations \
{ \
UIViewController <DeprecatedRotationSupported> *selfTyped = (UIViewController <DeprecatedRotationSupported> *) self; \
\
if(![self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) return UIInterfaceOrientationMaskPortrait; \
\
NSUInteger supported = 0; \
\
if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) supported |= UIInterfaceOrientationMaskPortrait; \
if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) supported |= UIInterfaceOrientationMaskLandscapeLeft; \
if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) supported |= UIInterfaceOrientationMaskLandscapeRight; \
if([selfTyped shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) supported |= UIInterfaceOrientationMaskPortraitUpsideDown; \
return supported; \
} \
\
- (BOOL)shouldAutorotateToInterfaceOrientation
#else // We are building with the older API, leave shouldAutorotateToInterfaceOrientation alone.
#define shouldAutorotateToInterface_fixed shouldAutorotateToInterfaceOrientation
#endif // __IPHONE_6_0
Then, anywhere you use shouldAutorotateToInterfaceOrientation: instead use shouldAutorotateToInterface_fixed:
回答6:
Here is my Subclassed RootNavController.h
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger) supportedInterfaceOrientations
{
if (self.topViewController.view.superview)
{
return [self.topViewController supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationMaskPortrait;
}