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开始如何处理转屏
【3】iOS开发之屏幕旋转