iOS监听屏幕旋转的几种方式

7,964 阅读2分钟

1. 使用 viewWillTransitionToSize:withTransitionCoordinator: 监听屏幕旋转:

iOS9之前,最常用的监听函数是如下两个:

//转屏前回调函数
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)durationNS_DEPRECATED_IOS(3_0,8_0,"Implement viewWillTransitionToSize:withTransitionCoordinator: instead")__TVOS_PROHIBITED;

//转屏后回调函数
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientationNS_DEPRECATED_IOS(2_0,8_0)__TVOS_PROHIBITED;

但这两个协议方法已经在iOS9之后废弃了(虽然也可以继续调用,但官方不建议使用了)

文档提示,改用如下函数:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;

转屏前后的监听如下:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context){
        NSLog(@"转屏前调入");
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context){
        NSLog(@"转屏后调入");
    }];
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

但这个监听方法有个局限性,这个协议方法来自于<UIContentContainer>,而查看官方代码可知,只有UIViewController及其子类,才能遵循并实现这个协议方法。即只有UIViewController才能够使用这个方法监听到 (且UIViewController是以一个类实例存在的)

2. 通过 UIDeviceOrientationDidChangeNotification 通知监听:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    //开始生成 设备旋转 通知
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    
    //添加 设备旋转 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:)  name:UIDeviceOrientationDidChangeNotification object:nil];
}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    //销毁 设备旋转 通知
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIDeviceOrientationDidChangeNotification
                                                  object:nil
     ];

    //结束 设备旋转通知
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}

/**屏幕旋转的通知回调*/
- (void)orientChange:(NSNotification *)noti {
    UIDeviceOrientation  orient = [UIDevice currentDevice].orientation;
    switch (orient) {
        case UIDeviceOrientationPortrait:
            NSLog(@"竖直屏幕");
            break;
        case UIDeviceOrientationLandscapeLeft:
            NSLog(@"手机左转");
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            NSLog(@"手机竖直");
            break;
        case UIDeviceOrientationLandscapeRight:
            NSLog(@"手机右转");
            break;
        case UIDeviceOrientationUnknown:
            NSLog(@"未知");
            break;
        case UIDeviceOrientationFaceUp:
            NSLog(@"手机屏幕朝上");
            break;
        case UIDeviceOrientationFaceDown:
            NSLog(@"手机屏幕朝下");
            break;
        default:
            break;
    }
}

这里监听的是屏幕方向。UIDeviceOrientation除了横竖屏4个方向以外,还包括“屏幕朝上”、“屏幕朝下”这两个方向,处理业务逻辑时需要注意着两个方向的特殊性。 因为通知的便利性,所以监听不需要局限于UIViewController里,而是任意位置。但注意要及时移除掉通知。

3. 通过 UIApplicationDidChangeStatusBarOrientationNotification 通知监听:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    //添加 设备旋转 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    //销毁 设备旋转 通知
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationDidChangeStatusBarOrientationNotification
                                                  object:nil];
}

/**屏幕旋转的通知回调*/
- (void)orientChange:(NSNotification *)noti {
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    switch (orientation) {
        case UIInterfaceOrientationUnknown:
            NSLog(@"未知");
            break;
        case UIInterfaceOrientationPortrait:
            NSLog(@"竖直");
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            NSLog(@"屏幕倒立");
            break;
        case UIInterfaceOrientationLandscapeLeft:
            NSLog(@"手机水平,home键在左边");
            break;
        case UIInterfaceOrientationLandscapeRight:
            NSLog(@"手机水平,home键在右边");
            break;
        default:
            break;
    }
}

整体同理于方法2,但有一些区别。获取到的方向是UIInterfaceOrientation,即界面方向,只有“上下左右”4个方向。

PS:[UIApplication sharedApplication].statusBarOrientation在iOS13之后会被废弃掉,官方建议使用window的方向。即如下:

[UIApplication sharedApplication].windows.firstObject.windowScene.interfaceOrientation

但这个API也只能在iOS13之后才能使用。

参考文档:

【1】IOS9开始如何处理转屏

【2】UIApplication

【3】iOS开发之屏幕旋转