iOS 屏幕旋转的实践解析( 二 )


 
/*This method is called when the view controller's view's size ischanged by its parent (i.e. for the root view controller when its window rotates or is resized).If you override this method, you should either call super topropagate the change to children or manually forward the change to children. */- (void)viewWillTransitionToSize:(CGSize)sizewithTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];[coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>_Nonnull context) {//横屏:size.width > size.height//竖屏: size.width < size.heightNSLog(@"旋转完成 , 更新布局");}];} 
三、相关问题 
在开发旋转场景的需求的时候 , 由于复杂的多级配置和数目繁多的枚举类型 , 难免会遇到一些崩溃和无法旋转的问题 , 下面我们就来总结一下此类问题 。
 
问题一:无法自动旋转首先检查下系统屏幕旋转开关是否被锁定 。系统屏幕锁定开关打开后,应用内无法自动旋转,但是可以调用上文提到的的方法进行手动旋转 。

iOS 屏幕旋转的实践解析

文章插图
 
问题二:多级屏幕旋转控制设置错误以下方法都可以设置屏幕旋转的全局权限:
 
Device Orientation 属性配置:“TARGETS > General > Deployment Info > Device Orientation”,图中是 xcode 默认的配置,值得注意的是 iPhone 不支持旋转到 Upside Down 方向 。
iOS 屏幕旋转的实践解析

文章插图
 
Appdelegate的 supportedInterfaceOrientationsForWindow 方法:
// 返回需要支持的方向// 如果我们实现了Appdelegate的这一方法,那么我们的App的全局旋转设置将以这里的为准- (UIInterfaceOrientationMask)application:(UIApplication *)applicatio supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window {return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskPortrait;} 
 
 
 
以上两种方式优先级:Appdelegate方法 > Target配置,这两种方式的配置和控制器的 supportedInterfaceOrientations 方法都会影响最终视图控制器最终支持的方向 。
 
以 iOS 14 中以 present 打开控制器的方式为例,当前控制器最终支持的屏幕方向 , 取决于上面两种方式中的优先级最高的方式的值 , 与控制器 supportedInterfaceOrientations 的交集 。
 
总结起来有以下几种情况:
 
如果交集为空,且在控制器的 shouldAutorotate 方法中返回为 YES,则会发生UIApplicationInvalidInterfaceOrientation 的崩溃 。
如果交集为空,且在控制器的 shouldAutorotate 方法中返回为 NO,控制器的supportedInterfaceOrientations 方法与 preferredInterfaceOrientationForPresentation 方法返回值不冲突(前者返回值包含有后者返回值),则显示为控制器配置的方向 。
如果交集为空,且在控制器的 shouldAutorotate 方法中返回为 NO,控制器的supportedInterfaceOrientations 方法与 preferredInterfaceOrientationForPresentation 方法返回值冲突(前者返回值未包含有后者返回值),则会发生 UIApplicationInvalidInterfaceOrientation 的崩溃 。
如果交集不为空 , 控制器的 supportedInterfaceOrientations 方法与 preferredInterfaceOrientationForPresentation 方法返回值冲突,则会发生 UIApplicationInvalidInterfaceOrientation 的崩溃 。
如果交集不为空,控制器的 supportedInterfaceOrientations 方法与 preferredInterfaceOrientationForPresentation 方法返回值不冲突,当前控制器则根据 shouldAutorotate 返回值决定是否在交集的方向内自动旋转 。
这里建议如果没有全局配置的需求 , 就不要变更 Target 属性配置或实现 Appdelegate 方法,只需在要实现旋转效果的 ViewController 中按前面所说的方式去实现代码 。
 
问题三:横屏时打开系统锁定屏幕开关,视图被强制恢复到竖屏由于 iOS 闭源,苹果为什么会这样操作当然我们也无从得知,但是我们可以通过一些手段来规避这个问题 。好在产生这样的旋转时 , 系统也会触发和普通旋转时一样的方法调用 。
 
以 iPhone X 为例,当下拉打开控制页面时,我们会收到 UIApplicationWillResignActiveNotification 的系统通知,收起控制页面后会收到 UIApplicationDidBecomeActiveNotification 通知,通过这两个通知来记录一下状态,在 shouldAutorotate 通过判断是否是 Active 状态 返回 YES/NO 。


推荐阅读