ios屏幕旋转:当全屏模式(此时是横屏模式)时,把app退后台然后再进入app时,横屏模式变成竟然变成了竖屏模式的解决方法。
步骤1:先看下图苹果文档的discussion部分。但这句话应该这样读:
①This method returns the total set of interface orientations supported by the app.意思是该方法返回的是app所支持的界面旋转方向集合。
②对于When determining whether to rotate a particular view controller, the orientations returned by this method are intersected with the orientations supported by the root view controller or topmost presented view controller.,这句话先看When determining whether to rotate a particular view controller,,意思是某个VC界面的方向取决于。 接着看the orientations returned by this method are intersected with the orientations supported by the root view controller or topmost presented view controller.,这句话比较长,在读英语句子的时候,如果句子比较长,可以先找出句子的主干,因为句子的主干就代表了这句话的意思,那怎么找出这句话的主干呢?答案是,第一步,先找出动词,因为这句话是一般时态,所以很明显are就是动词,因为一个英语句子里面只能有一个动词,所以returned和supported都是被动语态,被动语态可以当做定语,所以returned和supported都是定语,所以进入第二步,去掉定语,returned by this method表示该方法的返回值,supported by the root view controller or topmost presented view controller表示根VC或者最顶层的被present的VC,去掉returned by this method和supported by the root view controller or topmost presented view controller这两个定语;第三步,看主干,此时句子的主干就是the orientations are intersected with the orientations,翻译成中文的意思就是 ’方向集合‘和’方向集合‘的交集,前一个’方向集合’由returned by this method定语修饰,所以前一个‘方向集合’指的是application:supportedInterfaceOrientationsForWindow:方法返回的‘方向集合’,而后一个‘方向集合’被supported by the root view controller or topmost presented view controller这个定语修饰,所以后一个‘方向集合’就是 “根VC” 或者 “被present的顶部VC”的supportedInterfaceOrientations()方法返回的‘方向集合’。综上,When determining whether to rotate a particular view controller, the orientations returned by this method are intersected with the orientations supported by the root view controller or topmost presented view controller.意思就是一个VC界面最终所支持的旋转方向取决于:AppDelegate的application:supportedInterfaceOrientationsForWindow:方法返回的‘方向集合’和 【“根VC” 或者 “被present的顶部VC”的supportedInterfaceOrientations()方法返回的‘方向集合’】的交集。但在实际demo所验证的结论是: 第①种情况,当前屏幕的topmostVC是被present出来的,并且topmostVC的modalPresentationStyle是UIModalPresentationOverFullScreen或者UIModalPresentationFullScreen,即topmostVC占据了整个屏幕(能占据整个屏幕的topmostVC指的是present目标VC前,你给目标VC的modalPresentationStyle属性设置了UIModalPresentationOverFullScreen或者UIModalPresentationFullScreen。),此时你app在屏幕上正在展示的所有VC所处的旋转方向(默认是竖屏方向)取决于(AppDelegate的application:supportedInterfaceOrientationsForWindow:方法返回的‘方向集合’)∩(topmostVC的supportedInterfaceOrientations方法返回的‘方向集合’);第②种情况,当前屏幕的topmostVC不是被present出来的,或者topmostVC是被present出来但其没有占据整个屏幕(即topmostVC的modalPresentationStyle既是UIModalPresentationOverFullScreen也不是UIModalPresentationFullScreen),此时你app在屏幕上正在展示的所有VC所处的旋转方向(默认是竖屏方向)取决于(AppDelegate的application:supportedInterfaceOrientationsForWindow:方法返回的‘方向集合’)∩(rootVC的supportedInterfaceOrientations方法返回的‘方向集合’)。建议:既然the orientations returned by this method are intersected with the orientations supported by the root view controller or topmost presented view controller,那么你就重写rootVC的topVC里面的supportedInterfaceOrientations()方法,重写成if (self.presentedViewController && !self.presentedViewController.isBeingPresented && !self.presentedViewController.isBeingDismissed && [self.presentedViewController isKindOfClass:FullscreenViewController.class]) { return self.presentedViewController.supportedInterfaceOrientations; } return [super supportedInterfaceOrientations];
③The app and view controller must agree before the rotation is allowed.意思是只有VC的shouldAutorotate方法返回YES时,VC界面才可能会随着手机屏幕的旋转而旋转!

步骤2,如果上述不想看,直接看下面的结论:
界面支持的屏幕旋转方向 = “AppDelegate的application:supportedInterfaceOrientationsForWindow:方法返回的‘方向集合’” 和 "fun()方法返回的‘方向集合’"的交集。其中,fun()方法的实现如下:
- (UIInterfaceOrientation)fun {
if (topmostVC是被present出来的) {
if (topmostVC是占据了整个屏幕) {
if ([topmostVC shouldAutorotate]) {
return [topmostVC supportedInterfaceOrientations];
} else {
return 界面不随手机的旋转而旋转
}
} else {
return [rootVC supportedInterfaceOrientations]; //rootVC就是你app的UIWindow的rootViewController
}
}
}
设置app工程所支持的旋转方向,该设置会使整个全局生效。并且,如果在下图的设置里面只支持A方向,那么工程代码里面的VC就不能旋转到B方向。所以下图的方向基本上都是全部打钩。

本文代码都是基于genel里面设置了支持全部屏幕方向(如下图)为背景实现的

场景1:app只有一个VC
demo1
代码如下所示
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
ViewController *vc = [ViewController new];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
@end
如下图,在ViewController中重写shouldAutorotate()和supportedInterfaceOrientations()方法

结论:从上图的打印结果可以看出,shouldAutorotate()默认返回yes,即默认支持 跟随重力旋转手机而自动旋转VC的界面。supportedInterfaceOrientations()返回30,30对应的enum值是UIInterfaceOrientationMaskAll,即支持所有方向的旋转。不信你就旋转你的手机试试。。
demo2
在demo1的基础上,保持AppDelegate代码不变,修改ViewController的代码,代码如下
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.blueColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight; //该VC支持右横屏
}
@end
结果如下图,ViewController和Window都处于横屏,此时你的手机无论怎么旋转,ViewController的界面都是不会跟着旋转的。因为ViewController的supportedInterfaceOrientations()返回的是UIInterfaceOrientationMaskLandscapeRight,即VC只支持右横屏。

demo3, shouldAutorotate()返回NO
修改ViewController的代码,代码如下
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.blueColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"即使shouldAutorotate()返回的是NO,这个方法也会被调用.只不过该VC的界面不会跟着手机的旋转而发生旋转,因为shouldAutorotate()返回的是NO");
return [super supportedInterfaceOrientations];
}
@end
运行结果如下图。因为shouldAutorotate()返回NO,所以该VC的界面不会跟着手机的旋转而发生旋转。但是手机旋转到新的方向后(比如从竖屏旋转到横屏),shouldAutorotate()和supportedInterfaceOrientations()都会被调用,只不过因为shouldAutorotate()返回的是NO,所以supportedInterfaceOrientations()即使返回UIInterfaceOrientationMaskAll也不会导致界面随着手机的旋转而旋转。

demo4, shouldAutorotate()返回NO,supportedInterfaceOrientations()返回UIInterfaceOrientationMaskLandscapeRight
修改ViewController的代码,代码如下
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.blueColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"即使shouldAutorotate()返回的是NO,这个方法也会被调用.只不过该VC的界面不会跟着手机的旋转而发生旋转,因为shouldAutorotate()返回的是NO");
return UIInterfaceOrientationMaskLandscapeRight;
}
@end
运行结果如下图。因为shouldAutorotate()返回NO,所以该VC的界面不会跟着手机的旋转而发生旋转。但是手机旋转到新的方向后(比如从竖屏旋转到横屏),shouldAutorotate()和supportedInterfaceOrientations()都会被调用,只不过因为shouldAutorotate()返回的是NO,所以supportedInterfaceOrientations()即使返回UIInterfaceOrientationMaskLandscapeRight也不会导致界面随着手机的旋转而旋转。注意的是,VC的界面是横屏的(具体是向右横屏)


场景2:NavigationController+VC
demo1,一个NavigationController+1个VC
如下图所示,Window的rootVC是MyNavigationController,而MyNavigationController的rootVC是ViewController。

MyNavigationController的核心代码如下
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
BOOL flag = [super shouldAutorotate];
NSLog(@"%s, shouldAutorotate=%d", __func__, flag);
return flag;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UIInterfaceOrientationMask orientations = [super supportedInterfaceOrientations];
NSLog(@"%s, orientations=%llu", __func__, orientations);
return orientations;
}
@end
AppDelegate的核心代码如下
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = UIColor.blueColor;
ViewController *vc = [ViewController new];
MyNavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nvc;
[self.window makeKeyAndVisible];
return YES;
}
@end
ViewController的核心代码如下
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.redColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"即使shouldAutorotate()返回的是NO,这个方法也会被调用.");
return UIInterfaceOrientationMaskLandscapeRight;
}
@end
运行结果如下图.此时你旋转屏幕,VC界面也会随着手机的旋转而旋转,说明VC的shouldAutorotate()失效,而真正起作用的是MyNavigationController的shouldAutorotate()。NavigationController的shouldAutorotate()默认也返回yes,即默认支持 跟随重力旋转手机而自动旋转VC的界面,supportedInterfaceOrientations()默认也返回30,30对应的enum值是UIInterfaceOrientationMaskAll,即支持所有方向的旋转。

demo2
此时在MyNavigationController的shouldAutorotate()返回NO,而在ViewController的shouldAutorotate()返回YES,代码如下
MyNavigationController代码
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;//本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UIInterfaceOrientationMask orientations = [super supportedInterfaceOrientations];
NSLog(@"%s, orientations=%llu", __func__, orientations);
return orientations;
}
@end
ViewController代码如下
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.redColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return YES; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"即使shouldAutorotate()返回的是NO,这个方法也会被调用.");
return UIInterfaceOrientationMaskLandscapeRight;
}
运行结果如下,此时旋转手机发现,VC界面并不会跟着手机的旋转而旋转,所以VC的shouldAutorotate()失效,而真正起作用的是MyNavigationController的shouldAutorotate()。

demo3
我们希望每一个界面所支持的方向都由当前VC来控制,因为这样灵活性比较高,所以我们只需在NavigationController的shouldAutorotate()和supportedInterfaceOrientations()方法中返回栈顶VC的相应方法即可完成我们的目标。代码如下
MyNavigationController的代码如下
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return self.topViewController.shouldAutorotate; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return self.topViewController.supportedInterfaceOrientations; //本次修改
}
@end
运行结果如下,此时旋转手机发现,VC界面并不会跟着手机的旋转而旋转,因为MyNavigationController的shouldAutorotate()和supportedInterfaceOrientations()都由其栈顶的VC(本例为ViewController)的相应方法决定,又因为VC的supportedInterfaceOrientations()返回UIInterfaceOrientationMaskLandscapeRight,即只支持向右横屏,此时无论VC的shouldAutorotate()是否返回YES(这种情况下返回NO的结果也相同),旋转手机会发现,VC界面并不会跟着手机的旋转而旋转。

demo4
AppDelegate代码如下
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = UIColor.blueColor;
ViewController *vc = [ViewController new];
MyNavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nvc;
[self.window makeKeyAndVisible];
return YES;
}
@end
MyNavigationController代码如下
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
NSString *a = nil;
NSString *b = nil;
NSString *c = @"";
NSLog(@"%d, %d", [a isEqualToString:b], [c isEqualToString:b]);
NSLog(@"%s", __func__);
return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return self.topViewController.supportedInterfaceOrientations;
}
@end
ViewController代码如下
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(100, 10, 100, 100)];
self.button.backgroundColor = UIColor.redColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.view addSubview:self.button];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;//本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return [super supportedInterfaceOrientations];//本次修改
}
@end
运行结果如下两张图,如果app打开时手机处于竖屏状态,那么VC界面就是竖屏状态(下面第1张图),而如果app打开时手机处于横屏状态,那么VC界面就是横屏状态(下面第2张图).因为VC的shouldAutorotate()返回为NO,所以此时旋转手机发现,VC界面并不会跟着手机的旋转而旋转。


场景3:NavigationController+VC + AlertVC
demo1
AppDelegate代码如下
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = UIColor.blueColor;
ViewController *vc = [ViewController new];
MyNavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nvc;
[self.window makeKeyAndVisible];
return YES;
}
@end
MyNavigationController代码如下
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return self.topViewController.supportedInterfaceOrientations;
}
@end
ViewController代码如下
#import "MyAlertVC.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(10, 100, 100, 100)];
self.button.backgroundColor = UIColor.redColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.button addTarget:self action:@selector(presentClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button];
}
- (void)presentClick {
MyAlertVC *actionSheetController = [MyAlertVC alertControllerWithTitle:@"手机空间不足" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cealrVideoAction = [UIAlertAction actionWithTitle:@"清理离线下载视频" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
UIAlertAction *clearPhoneAction = [UIAlertAction actionWithTitle:@"清理手机空间" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (@available(iOS 10, *)) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
#pragma clang diagnostic pop
}else {
[[UIApplication sharedApplication] openURL:url];
}
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"3333" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[actionSheetController addAction:cealrVideoAction];
[actionSheetController addAction:clearPhoneAction];
[actionSheetController addAction:cancelAction];
[self presentViewController:actionSheetController animated:YES completion:nil];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return [super supportedInterfaceOrientations];
}
@end
MyAlertVC代码如下
@implementation MyAlertVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate {
BOOL flag = [super shouldAutorotate];
NSLog(@"%s, autorotate=%d", __func__, flag);
return flag;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UIInterfaceOrientationMask orientations = [super supportedInterfaceOrientations];
NSLog(@"%s,orientations=%llu", __func__, orientations);
return orientations;
}
@end
运行结果如下图
点击红色按钮,结果如下图。从orientation=30的结果可以知道UIAlertController默认和其父类UIViewController一样支持各个方向的旋转。所以此时旋转手机发现,所有VC界面(比如VC界面和AlertVC界面)都会跟着手机的旋转而旋转。

demo2
修改MyAlertVC,shouldAutorotate()返回YES,supportedInterfaceOrientations()返回UIInterfaceOrientationMaskLandscapeRight。代码如下
@implementation MyAlertVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__); //本次修改
return YES; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);//本次修改
return UIInterfaceOrientationMaskLandscapeRight;//本次修改
}
@end
运行结果如下图:当点击红色按钮弹出AlertVC时,AlertVC并没有按横屏弹出。。并且此时系统只调用了supportedInterfaceOrientations()而没有调用shouldAutorotate()。此时旋转手机屏幕时,如果旋转到非UIInterfaceOrientationMaskLandscapeRight,那么所有VC界面都不会随着旋转,而如果旋转到UIInterfaceOrientationMaskLandscapeRight方向时,所有VC界面都会随着旋转到UIInterfaceOrientationMaskLandscapeRight方向,之后无论手机怎么旋转,所有界面VC都不会旋转了。。

demo3
MyAlertVC的shouldAutorotate()返回NO
@implementation MyAlertVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return UIInterfaceOrientationMaskLandscapeRight;
}
@end
运行结果如下图,当点击红色按钮弹出AlertVC时,AlertVC并没有按横屏弹出。。并且此时系统只调用了supportedInterfaceOrientations()而没有调用shouldAutorotate()。此时旋转手机屏幕时,AlertVC的shouldAutorotate()会被调用,因为返回值为NO,所以所有VC界面都不会随着手机的旋转

场景4:UITabBarController+NavigationController+VC
demo1
AppDelegate代码如下
#import "AppDelegate.h"
#import "ViewController.h"
#import "MyNavigationController.h"
#import "MyTabBarVC.h"
#import "EmptyVC.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = UIColor.blueColor;
ViewController *vc = [ViewController new];
MyNavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:vc];
MyTabBarVC *tabVC = [[MyTabBarVC alloc] init];
nvc.tabBarItem.title = @"测试VC";
[tabVC addChildViewController:nvc];
//不需要管emptyVC,只是让你知道有个tabVC就ok
EmptyVC *emptyVC = [EmptyVC new];
emptyVC.tabBarItem.title = @"你不用管";
[tabVC addChildViewController:emptyVC];
self.window.rootViewController = tabVC;
[self.window makeKeyAndVisible];
return YES;
}
@end
MyNavigationController代码如下
@interface MyNavigationController ()
@end
@implementation MyNavigationController
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return self.topViewController.supportedInterfaceOrientations;
}
@end
ViewController代码如下
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.button = [[UIButton alloc] initWithFrame:CGRectMake(10, 100, 100, 100)];
self.button.backgroundColor = UIColor.redColor;
[self.button setTitle:@"按钮" forState:UIControlStateNormal];
[self.button addTarget:self action:@selector(presentClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button];
}
- (void)presentClick {
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__);
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__);
return [super supportedInterfaceOrientations];
}
@end
运行结果如下图。从打印结果可以看出,UITabBarController默认支持自动旋转,并且支持各个方向的旋转(因为orientations==30,30对应UIInterfaceOrientationMaskAll)。此时所有VC界面都会随着手机屏幕的旋转而旋转。

demo2
在demo1的基础上,只修改MyTabBarVC的shouldAutorotate()返回值
@implementation MyTabBarVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s", __func__); //本次修改
return NO; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s", __func__); //本次修改
return [super supportedInterfaceOrientations];
}
@end
打印结果如下,此时旋转手机屏幕,所有VC界面并不会随着手机屏幕的旋转而旋转

demo3
在demo1的基础上,修改MyTabBarVC的shouldAutorotate()和supportedInterfaceOrientations()的返回值为selectedViewController的相应方法的返回值。
@implementation MyTabBarVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate {
NSLog(@"%s,self.selectedViewController=%@", __func__, self.selectedViewController);
return self.selectedViewController.shouldAutorotate; //本次修改
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s,self.selectedViewController=%@", __func__, self.selectedViewController);
return self.selectedViewController.supportedInterfaceOrientations;//本次修改
}
@end
运行结果如下图,此时旋转手机屏幕,会发现所有的VC界面都不会随着屏幕的旋转而旋转,因为ViewController的shouldAutorotate()返回NO。如果此时你把ViewController的shouldAutorotate()返回值设为YES,那么旋转手机屏幕,会发现所有的VC界面都会随着屏幕的旋转而旋转。

shouldAutorotate
当界面不存在被present的VC时,你的界面是否支持自动旋转是由UIWindow的rootViewController(下文简称rootVC)的shouldAutorotate()的返回值决定的。
当界面的topmost是被present的VC时,你的界面是否支持自动旋转是由下面的fun()函数决定的。
- (BOOL)fun {
if (topmostVC是全屏展示) { //即topmostVC.modalPresentationStyle的值为UIModalPresentationFullScreen或者UIModalPresentationOverFullScreen
if (![topmostVC shouldAutorotate]) {
return NO;
} else {
if (topmostVC.modalPresentationStyle == UIModalPresentationFullScreen) {
return YES;
} else { //能执行下一行代码说明topmostVC.modalPresentationStyle == UIModalPresentationOverFullScreen
return [rootVC shouldAutorotate];
}
}
} else {
return [rootVC shouldAutorotate];
}
}
最后
以上就是自然项链最近收集整理的关于VC的shouldAutorotate和supportedInterfaceOrientations方法的学习demoshouldAutorotate的全部内容,更多相关VC内容请搜索靠谱客的其他文章。
发表评论 取消回复