http://blog.youkuaiyun.com/ccwf2006/article/details/53259939
一.其实屏幕旋转不是什么玄学.
1.在 plist 文件里直接设置支持的方向.
2.如果 plist 文件中支持多个方向,那么在方向改变时,系统会询问 keyWindow 的 rootViewController,调用这两个方法来决定是否可以旋转.
- (BOOL)shouldAutorotate{
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
必须在 rootViewController 里面实现这两个方法.
- (BOOL)shouldAutorotate{
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
if ([self.selectedViewController isKindOfClass:[RiceNavigationController class]]) {
RiceNavigationController* tempController = (RiceNavigationController*)self.selectedViewController;
if ([tempController.topViewController respondsToSelector:@selector(supportedInterfaceOrientations)]) {
return [tempController.topViewController supportedInterfaceOrientations];
}
}else if ([self.selectedViewController respondsToSelector:@selector(supportedInterfaceOrientations)]){
return [self.selectedViewController supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait;
}
在我的项目里, rootViewController 是 TabBar,上面的代码是 Tabbar 尝试询问当前最顶层的 ViewController 来决定支持的方向.
PresentViewController 不需要处理,因为, Present 状态的 ViewController 方向是由系统直接管理的.
如果从一个只支持竖屏的 ViewController 进入到横屏竖屏都支持的 ViewController, 上面的代码就够了.
如果进入到一个只支持竖屏的 ViewController 还需要处理一下.
1. 从只支持竖屏的 ViewController 跳转到只支持横屏的 ViewController, 屏幕方向并不会变化.
可以调用私有方法强制修改设备当前的方向.
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
[[UIDevice currentDevice] performSelector:@selector(setOrientation:)
withObject:(id)UIInterfaceOrientationLandscapeRight];
}
这个现在是私有方法,但是通过performSelector 不会被查到.
然而,这样会造成系统内部的 DeviceOrientation 与实际不符, 特定的 ViewController Pop 以后,设备方向依旧是横向,会出现 BUG.
2.使用 present 的方式弹出只支持横屏的 ViewController.
需要注意的是, UINavigationController 似乎会调用
- (BOOL)shouldAutorotate;
- (UIInterfaceOrientationMask)supportedInterfaceOrientations;
这两个方法来决定 pop 操作后出现的 ViewController 的方向.所以,每一个push 到 UINavigationController 的 ViewController 都应该实现这两个方法.
之所以这个问题看起来像玄学,主要是苹果设计的耦合性太高了,不能像 UINavigationBar 设置样式一样,用当前的 UIViewController 来设置,导致个别 UIViewController 需要屏幕旋转而大多数不需要旋转这个问题比较难以解决.
系统旋转屏幕的原理可以参考:
http://www.cnblogs.com/smileEvday/archive/2013/04/23/Rotate1.html
http://www.cnblogs.com/smileEvday/archive/2013/04/24/Rotate2.html