Developer J.K.

明明可以靠颜值吃饭但偏偏想要写代码做产品的jaykon

iOS4-iOS7屏幕旋转的控制

之前做了一个应用,但由于整应用界面个都是竖屏,不允许横屏,所以一直没有关注这个,昨天开发一个图片预览的类库(类似系统的查看图片),其中一个特性当然需要支持横屏,所以就压找了一下资料,之前已经听闻在屏幕控制上,iOS6上有了比较坑爹的变化。比如,让视图支持正常坚屏和两种横屏,兼容的做法是:

//for iOS4,iOS5
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation==UIInterfaceOrientationMaskLandscape);
}

//for iOS6
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

还没有完事,在iOS4\5如果没有重写shouldAutorotateToInterfaceOrientation,则默认不旋转屏幕,而在iOS6上,如果没有重写shouldAutorotate和supportedInterfaceOrientations,则默认支持除UIInterfaceOrientationMaskPortraitUpsideDown外的3个高向。

最大的区别来了,iOS6顶层的controller(必须设置为window.rootViewController)决定了它及它下面所有子层的屏幕旋转属性,也就是说,如果顶层controller设为可旋转,它及它的子层不能设为不可旋转,相反亦然,因为子层的controller相关的supportedInterfaceOrientations和shouldAutorotate根本不会触发。

那如果现在有一个需求,非常常见,堆栈是window->navigationController->viewControllerA->viewControllerB
viewControllerA要求是竖直,viewControllerB要求可以支持多个方向。实际上这个在iOS6里面无法通过以前的方法实现,因为navigationController作为顶层controller决定了它的可旋转性。

比较方便的解决方法是,viewControllerB以presentModalViewController的方式出现,因为这样它不属于navigationController的堆栈,可以自行决定是否转向。

另一种方法是viewControllerB加入CoreMotion加速计,通过判断设备的手持方向来切换不同的视图,不过就比较麻烦了。