VC的shouldAutorotate和supportedInterfaceOrientations方法的学习demo

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 methodsupported 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];
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值