最近在做横竖屏切换的时候,发现一个crash,是一个平时没有注意到的点。
UIApplicationInvalidInterfaceOrientation', reason: 'preferredInterfaceOrientationForPresentation 'landscapeLeft' must match a supported interface orientation: 'portrait'!
从描述上看,错误很明显,我们从方法的描述上看看。
Returns the interface orientation to use when presenting the view controller.
The system calls this method when presenting the view controller full screen. When your view controller supports two or more orientations but the content appears best in one of those orientations, override this method and return the preferred orientation.
If your view controller implements this method, your view controller’s view is shown in the preferred orientation (although it can later be rotated to another supported rotation). If you do not implement this method, the system presents the view controller using the current orientation of the status bar.
那么如果supportedInterfaceOrientations
和preferredInterfaceOrientationForPresentation
返回的内容不符,是不是就会crash,经过试验的确会crash。
但是我们在dismiss
的时候呢,经过试验表明,也是会crash的,特别是preferredInterfaceOrientationForPresentation
返回的是UIApplication.shared.statusBarOrientation
时,是一个非常容易被忽略的问题。
那么push呢?表现是怎么样的?
经过试验,在pop的时候,如果横竖屏状态不一致,并不会crash,但是转场动画采用了系统默认的了,不会进入转场动画的delegate。
所以,如果需要做流畅的转场以及横竖屏切换,在一些场合下,还是需要使用present方式,并且需要在双方都确保supportedInterfaceOrientations
和preferredInterfaceOrientationForPresentation
的正确。
自定义动画
在做自定义转场动画的时候,可以注意到,如果是从竖屏进入横屏的动画过程中,横竖屏的状态是正确的,但是横竖屏状态只能存在一个,也就是[UIDevice currentDevice].orientation
,那么系统是怎么做到的呢。
重写UIViewControllerAnimatedTransitioning
中的动画方案- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
,在此时获取屏幕方向[UIApplication sharedApplication].statusBarOrientation
,发现已经转换到下一个controller的方向了,那么前一个controller为什么显示正常呢。我们看一下前一个fromController.view.transform
,发现他并不是CGAffineTransformIdentity
,这样就一目了然了。系统在屏幕转向变化的时候,会把上一个视图自动旋转90度,这样就可以无缝的转场动画。
那么另一个问题是,此时的controller的生命周期会是怎么样的。经过尝试,此时已经在viewWillAppear:
和viewWillDisappear
之后了,符合我们的预期。